S16 and File::Spec/Cwd/PathTools
Should the functionality of File::Spec and Cwd be integrated into the IO modules? I'm not advocating the interface, but the functionality might be useful. Thanks, - | Name: Tim Nelson | Because the Creator is,| | E-mail: wayl...@wayland.id.au| I am | - BEGIN GEEK CODE BLOCK Version 3.12 GCS d+++ s+: a- C++$ U+++$ P+++$ L+++ E- W+ N+ w--- V- PE(+) Y+>++ PGP->+++ R(+) !tv b++ DI D G+ e++> h! y- -END GEEK CODE BLOCK-
Re: S16 and File::Spec/Cwd/PathTools
* Timothy S. Nelson (wayl...@wayland.id.au) [090217 08:13]: > Should the functionality of File::Spec and Cwd be integrated into > the IO modules? I'm not advocating the interface, but the functionality > might be useful. We had a very long discussion about this subject on this list, last November. And yes, I agree with this closer code relationship between IO objects and operations on them. Starting point: http://www.mail-archive.com/perl6-language@perl.org/msg28566.html -- MarkOv Mark Overmeer MScMARKOV Solutions m...@overmeer.net soluti...@overmeer.net http://Mark.Overmeer.net http://solutions.overmeer.net
Re: infectious traits and pure functions
Jon Lang wrote: I'm not saying that it needs to decide whether or not you have a halting problem; I'm saying that if there's any possibility that you _might_ have one, you should stop looking. Let's take it as a given that things such as exceptions, threads, and co-routines make the automated establishment of whether or not a given function is pure a nightmare. The easy solution for this would be to say that if a given function makes use of exceptions, threads, or co-routines, it will not be auto-tagged as pure. The process of auto-tagging pure functions would not be perfect, in that there are likely to be a number of functions that are in fact pure but don't get auto-tagged as such; but it could still be _good_, in the sense that a useful set of pure functions _would_ be auto-tagged. One thing I want to make clear is that any validation of purity or auto-tagging of said should be based on a whitelist, not on a blacklist. You have to think of this like you think of security. Don't look for a list of things that might give you problems, rather look to see if you have anything at all that isn't known to be safe. A given entity (type/routine/etc) is pure iff all of its dependencies (referenced types or operators etc) are pure. Any unknown means unpure. To start off with, all the system-defined (defined in the Perl 6 synopsis documents) types and operators should be explicitly tagged as either pure or impure. Then when compiling user code, we know that code is pure iff all of its dependencies are either said system-defined pure ones or are each other. And yes, as you said, if in doubt, mark unpure. I would also like to disagree with the idea that using exceptions means impure; I believe they can go together fine. Specifically, I believe it is just fine for a pure routine to throw an exception, though on the other hand perhaps a pure routine shouldn't be allowed to catch an exception; a thrown exception in the pure sandbox would cause that particular in sandbox call stack to return early with the net result being a no-op (save thrown exception), and an impure caller routine can then catch it if it wants. The fact the contents of the call stack could be arbitrarily compiler reordered doesn't change these semantics as seen outside the sandbox. In fact, one point of a pure sandbox is that an outside caller can in some respects just see the thing they directly call as an opaque thing which either succeeds and returns a valid answer for its declared type or it fails with an exception. One reason that supporting exceptions from pure routines is good is that a runtime exception is how you handle the general case of bad input. I say the general case because, while some things can be caught by the compiler (such as passing a Str typed variable to something wanting an Int), some arbitrary input constraints are too complicated and effectively become runtime checks anyway, since even determining if you have a violation at all could require a lot of runtime calculations and many routine calls. There are also other exceptions you can have due to, what in the broad sense isn't a type violation but in the strict sense is, such as numerical division. I don't think anyone would argue that numeric division is a pure function, and yet you can't get a normal answer if you give it a divisor of zero. Attempting to do so, you'd probably want an exception as a result. Now this all said, one alternative is Perl's Failure type, the unthrown exception, which may be a way around actual exceptions. I suppose that if all the pure routines knew how to special case an input of Failure and just abort and return Failure themselves, we can skip an actual exception. Particularly useful in those cases where you don't want your rocket to shutdown because one of a hundred redundant sensors failed. Except in some ways that is a bad example because reading from the environment like a sensor would never happen within the pure sandbox; it would have to happen prior to entering the sandbox and the sandbox be given a Failure input and hence abort. So in the end we effectively still have a thrown exception. I think our code would be cleaner if we can just use exceptions and not have to check return values. Now, all this assumes that throwing an exception has no side-effect besides the sandbox returning/throwing failure, and I assume an exception object is effectively pure itself. So, I see no problems with exceptions in a pure environment. I also don't think threads are necessarily a problem. If all the inputs to the pure sandbox are immutable values, and all called routines, that is the metamodel / classes / etc, are an immutable snapshot as of the sandbox entry time, and the pures don't see globals, then no thread can interfere with another within the pure sandbox. Co-routines, if they are pure routines, I don't expect to be a problem either, but I'm less sure about t
r25364 - docs/Perl6/Spec
Author: wayland Date: 2009-02-17 11:06:57 +0100 (Tue, 17 Feb 2009) New Revision: 25364 Modified: docs/Perl6/Spec/S16-io.pod Log: S16: Added cwd to FileSystem Modified: docs/Perl6/Spec/S16-io.pod === --- docs/Perl6/Spec/S16-io.pod 2009-02-17 08:38:53 UTC (rev 25363) +++ docs/Perl6/Spec/S16-io.pod 2009-02-17 10:06:57 UTC (rev 25364) @@ -439,6 +439,7 @@ This reads directories, deletes filesystem entries, creates links, and the like. class IO::FileSystem does IO::Streamable { + has IO::FileSystemEntry $cwd; ... } @@ -499,7 +500,7 @@ =head2 IO::FilesystemEntry -class IO::FileSystem { +class IO::FileSystemEntry { ... }
r25367 - docs/Perl6/Spec
Author: wayland Date: 2009-02-17 12:26:51 +0100 (Tue, 17 Feb 2009) New Revision: 25367 Modified: docs/Perl6/Spec/S16-io.pod Log: S16: Made some improvements based on http://www.mail-archive.com/perl6-language@perl.org/msg28566.html (Thanks to Mark Overmeer for the link) Modified: docs/Perl6/Spec/S16-io.pod === --- docs/Perl6/Spec/S16-io.pod 2009-02-17 10:55:14 UTC (rev 25366) +++ docs/Perl6/Spec/S16-io.pod 2009-02-17 11:26:51 UTC (rev 25367) @@ -68,6 +68,11 @@ you're going to need to encode it later, or use "getc" or other IO::Readable::Encoded methods. +=item method Bool is_readable() + +Indicates whether socket is actually opened for reading. Closed sockets +return false. + =back =head2 IO::Writeable @@ -87,6 +92,11 @@ encoded data, you should decode it first, or use "print" or other IO::Writeable::Encoded methods. +=item method Bool is_writeable() + +Indicates whether socket is actually opened for writing. Closed sockets +return false. + =back =head2 IO::Seekable @@ -411,7 +421,7 @@ =item init - method init(String $filename, $options?); + method init(Str $filename, $options?); method init(Int $fd); # Read @@ -439,7 +449,11 @@ This reads directories, deletes filesystem entries, creates links, and the like. class IO::FileSystem does IO::Streamable { - has IO::FileSystemEntry $cwd; + has IO::FileSystemEntry $.cwd; # Current working directory + has IO::FileSystemEntry $.basepath; # The Unix mount point, or Windows drive letter, or whatever + has Str $.type; # ext3, ntfs, vfat, reiserfs, etc + has Str $.illegal_chars; # ie. /\x0 + has Int $.max_path; ... } @@ -447,6 +461,12 @@ =item glob +Returns FileSystemEntry objects + +=item find + +Returns FileSystemEntry objects + =item link =item lstat @@ -501,6 +521,8 @@ =head2 IO::FilesystemEntry class IO::FileSystemEntry { + has Str $path; + has IO::FileSystemEntryACL @.acls; ... } @@ -662,8 +684,68 @@ the stat fails, all subsequent tests on the stat buffer also evaluate to false. +=item realpath + + method Str realpath(); + +Gets the real path to the object, resolving softlinks/shortcuts, etc + +=item parent + + method IO::FileSystemEntry parent(); + +=item isSameFile + + method isSameFile(Str $filename); + +Test whether the specified filename is the same file as this file. On a Unix system, +this would presumably be done by comparing inode numbers or something. + =back +=head2 IO::FileSystemEntryACL + +This is a basic abstraction; for better control, use the operating-system specific +interfaces [not designed yet], over which this is a thin veneer. + +class IO::FileSystemEntryACL { + has Str $.type; # "User", "Group", "Everyone", ??? + has Str $.id; # username or groupname; unused for $type eq "Everyone" + has %.permissions; + # Unsupported values may (or may not) throw + # UnsupportedPermission when set or read + has IO::FileSystemEntry $.owningObject; +... +} + +The permissions used in %permissions are: + +=over + +=item Readable + +Should be supported by all filesystems as an item to read from the hash for the group +"Everyone". + +=item Writeable + +Should be supported by all filesystems as an item to read from the hash for the group +"Everyone". + +=item Executeable + +Supported on most Unix systems, anyway + +=item Default + +An ACL of User,fred,Default sets the user "fred" to be the owner of the file. This can be +done with groups too. Work on Unix, at least. + +=back + +The $.owningObject attribute of FileSystemEntryACL shows what the ACL is set on. On a +Windows system, this can be a parent directory, as permissions are inherited. + =head2 IO::Socket::TCP class IO::Socket::TCP does IO::Socket does IO::Streamable {
IO, Trees, and Time/Date
Hi all. I know we usually run on forgiveness instead of permission, but I'm suggesting a big change (or extension, anyway), so I wanted to run the ideas by you all before I put the effort in. If I don't get feedback, I'll just make the changes. The first thing I wanted to suggest was that in S16, the OS-specific stuff be split out into separate roles. I suspect this is mostly non-controversial, so I'll do that unless someone complains. My second thought is that we need to specify tree objects (see http://www.mail-archive.com/perl6-language@perl.org/msg28579.html ). I'll put them in S16 unless someone complains. My third thought is that it would be very useful also to have date/time objects that integrate well with eg. ctime, mtime, and the like; I'd start with Time::Piece as a model. http://search.cpan.org/dist/Time-Piece/Piece.pm My final question is, since people are now getting somewhat familiar with the "file:" URI scheme (ie. file:/home/wayland/Notes.txt or file:/C/Documents and Settings/wayland/Notes.txt or whatever), I'm wondering if this isn't how we should be specifying our files; it's prettier than File::Spec :), and unified. Anyway, HTH, - | Name: Tim Nelson | Because the Creator is,| | E-mail: wayl...@wayland.id.au| I am | - BEGIN GEEK CODE BLOCK Version 3.12 GCS d+++ s+: a- C++$ U+++$ P+++$ L+++ E- W+ N+ w--- V- PE(+) Y+>++ PGP->+++ R(+) !tv b++ DI D G+ e++> h! y- -END GEEK CODE BLOCK-
Re: r25328 - docs/Perl6/Spec (fwd)
I didn't realise this hadn't gone to the list. Enjoy, all :). -- Forwarded message -- Date: Tue, 17 Feb 2009 14:34:07 +1100 (EST) From: Timothy S. Nelson To: Leon Timmermans Subject: Re: r25328 - docs/Perl6/Spec On Mon, 16 Feb 2009, Leon Timmermans wrote: On Mon, Feb 16, 2009 at 4:50 AM, Timothy S. Nelson wrote: I like it if we can make it work, but it may be too nonsensical to get anything useful out of it. See my discussion below. So far, all ideas based on it result in incredibly verbose code. Creating an IO object should only be one statement. Anything else is failure IMNSHO. I see the problem; lets see if we can address that one too :). First, let me reprint an example I gave below: $socket = new IO::Socket::INET($RemoteHost, $RemotePort, OtherOption => 1); $socket.Blockingness = 1; # Ok, maybe not blockingness, but you know what I mean $socket.OtherOption = 0; # Changed our mind from what we said in the class creation call $socket.open(); # This could be called "connect", maybe I wasn't very clear here in what I was trying to demonstrate. This example needed more "..." in it. I was assuming that the lines were not all immediately following each other, but I in no way communicated that; sorry :). Allow me to point out that if I wanted to write the first three lines of what I proposed above in a single call, I'd do it like this: $socket = new IO::Socket::INET($RemoteHost, $RemotePort, OtherOption => 0, Blockingness => 1, ); ...which I hope you'll agree is vaguely perlish. Hopefully we can also choose sensible defaults for all these options. My assumption was that people would sometimes want to create an IO object without opening/connecting it, which is why I separated the creation and .open() calls into two separate statements. But choosing sensible defaults applies here; what if we had it open by default on creation unless someone passes in a NoOpen => 1 option? Or maybe leave that to the implementations; files open by default, and sockets don't? This was an example of me not thinking. Basically, it was because it was easier than writing IO::Readable IO::Writeable. I'll ignore the question as it crops up throughout; someone feel free to replace POSIX with something else. Most of them should not be doing defined as implementing both. If a file is opened read-only, the object it returns should not be IO::Writeable. Hence, IO::File and such shouldn't be implementing IO::Readable or IO::Writeable. Such things should remain orthogonal, that is the whole idea of using roles! Ok, I'm vaguely starting to see the purpose of all this :). Say I do this: $fh = new IO::File($filename); while($_ = $fh.getline) { push @lines; } $fh.close(); Yes I know there are better ways to do it, but how does IO::Readable get there? Does it get mixed in at open time or something? As a rakudo user, I'm also wondering whether we shouldn't be referring more to the Parrot IO stuff, but that may just be me. Parrot has very different goals for its IO interface: being able to implement the IO of all implemented languages is more important than having the best possible interface. In short, it's an implementation detail. Sorry, I wasn't clear again. I was thinking more from the point of view that a number of the things we've said appear to refer to the underlying OS calls and how they map to Perl6. I was thinking maybe we should talk about how the Parrot calls map to Perl6 (in our discussion, not in the Spec). But Maybe they're similar enough anyway that it doesn't really matter :). Question -- is there a reason this is in IO, instead of eg. S29? If not, I'll move it there. AFAIK it's mostly used for obscure IO calls. I do agree it shouldn't really be in S16 though. Ok, I've moved it. Disagree -- I think these belong in IO::Unbuffered. Maybe we could make that optional, though :). It may have a purpose in IO::POSIX, but other than that it doesn't make too much sense to me. The interface is stuck in 1969. We should make our open flexible enough that it can handle the use cases that now require sysopen, without having the same sucky interface. Sorry, I was unclear. I don't think those calls belong in IO::Unbuffered, but that whatever does our open should, if the object does IO::Unbuffered, apply the correct parameters. But I agree with you about unification of interface. Hmm. I still haven't gotten the hang of Perl 6. What I want is for the name of this function to be the one that automatically gets called on object creation. Then you do something like this: $fobj = new IO::File($filename); # Creates handle $fobj.open(); # opens file Opening a file shouldn't be two lines, this is Perl! I think this whole Openable thing is harming us. Simple things should be simple. I agree about simplicity; see my comments at the top about
Detecting side-effects in Perl 6 (Was: Re: infectious traits and pure functions)
Em Seg, 2009-02-16 às 21:21 -0800, Darren Duncan escreveu: > marking it as consisting of just immutable values, and in the > routines case marking it as having no side effects The problem is that you can't really know wether a value is immutable or not, we presume a literal 1 to be immutable, but even if you receive :(Int $i), it doesn't mean $i is immutable, because that signature only checks if $i ~~ Int, which actually results in $i.does(Int). The twisted part is that $i.does(Int) is a regular method call on $i, which means that $i might be of whatever type, and be accepted by that signature by simply replying True on "does". The only exception to that rule are the native types, which are guaranteed to always be of that actual type, you can't "lie" about a native int, as you can with Int. Even then, you would have to check if all the multi-variants for the operators used in that function are free of side-effects as well, because no one stops you from writing: multi infix:<+> (int where { 2 } $i, int where { 2 } $j) { say "The Big Brother is Watching You!" return 5; } or worse multi infix:<+> (int where { 2 } $i, int where { 2 } $j) { return OtherTypeThatHasSideEffectsButDoesInt.new(:initial_value(5)); } So, while I agree that it would be very cool to make pure functions optimizeable somehow, you simply can't be sure about it. OTOH, S06 already propose an optimization hint, which should do what you want, look for "is cached". daniel
Re: Detecting side-effects in Perl 6 (Was: Re: infectious traits and pure functions)
Em Ter, 2009-02-17 às 09:19 -0300, Daniel Ruoso escreveu: > multi infix:<+> (int where { 2 } $i, int where { 2 } $j) {...} As masak++ and moritz++ pointed out, this should be written multi infix:<+> (int $i where 2, int $j where 2) {...} daniel
Re: IO, Trees, and Time/Date
Timothy S. Nelson wrote: Hi all. I know we usually run on forgiveness instead of permission, but I'm suggesting a big change (or extension, anyway), so I wanted to run the ideas by you all before I put the effort in. If I don't get feedback, I'll just make the changes. The first thing I wanted to suggest was that in S16, the OS-specific stuff be split out into separate roles. I suspect this is mostly non-controversial, so I'll do that unless someone complains. My second thought is that we need to specify tree objects (see http://www.mail-archive.com/perl6-language@perl.org/msg28579.html ). I'll put them in S16 unless someone complains. My third thought is that it would be very useful also to have date/time objects that integrate well with eg. ctime, mtime, and the like; I'd start with Time::Piece as a model. http://search.cpan.org/dist/Time-Piece/Piece.pm My final question is, since people are now getting somewhat familiar with the "file:" URI scheme (ie. file:/home/wayland/Notes.txt or file:/C/Documents and Settings/wayland/Notes.txt or whatever), I'm wondering if this isn't how we should be specifying our files; it's prettier than File::Spec :), and unified. Anyway, HTH, I like all the default suggestions. It seems to me that a path, whether within a file system or across the internet, leads to a location. A location is a container for files. A file is a container for data. Given the strong typing paradigm of Perl6, it seems to me that the specification should distinguish between files and locations. It seems to me that unix blurs the difference between a file and a directory (at least readdir returns both file and directory names and the programer then needs a test to distinguish them), but that does not mean they are not conceptually different. For example, it is sensible to have a .files() method for a directory, but it is not sensible for such a method to exist for a file. Meanwhile, print/say/putc are not sensible for a directory/location. Moreover, if perl6 distinguishes between a location and a file, then the spec can distinguish between a .children() method that provides a list of child locations (viz., sub-directories) and .files(), which provides a list of the contents of the location. Regards, Richard
Re: Detecting side-effects in Perl 6 (Was: Re: infectious traits and pure functions)
HaloO, Daniel Ruoso wrote: The problem is that you can't really know wether a value is immutable or not, we presume a literal 1 to be immutable, but even if you receive :(Int $i), it doesn't mean $i is immutable, because that signature only checks if $i ~~ Int, which actually results in $i.does(Int). 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 and puts that into $i and also instructs the underlying object system to check for purity violation in the scope of the signature. The presence of this trait in methods called on $i and parameters $i is given to can be checked by the compiler. A save mode would be to allow only calls that have the trait. This is far from a halting problem. Simple coverage analysis suffices. 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. With these purity locks by means of traits the aforementioned pure sandbox can be build. E.g. a module can be internally pure and receive impure objects in its interface converting them on the fly. Note that a signature must allow the pure trait also in the return type to allow for purity to spread. So the signature of Int addition might read multi infix:<+> (Int $x is pure, Int $y is pure --> Int is pure) which might be abbreviated with purity on the sub as such as a short-cut to purity in all slots. Also the dispatcher has to make impure candidates fail in the applicability stage. An altogether different question is the transition back from a purified object. Should that always create a new impure object or revert back to the original the snapshot was taken from? The latter would imply the original object piggybacked onto the pure snapshot. The snapshot mechanism has to be efficient to not loose the gains from purity in a heavily mixed setting. As such it has to be some copy on write scheme on the object level. multi infix:<+> (int where { 2 } $i, int where { 2 } $j) { say "The Big Brother is Watching You!" return 5; } Does a printout already constitute a side-effect? If so, it is at least not a dangerous one because it doesn't feed changed state back into the stream of a computation. The only danger is that a user wonders about the sequence of prints in the course of an optimized flow. IOW, say could have the 'is pure' trait on its parameters and on itself. OTOH, S06 already propose an optimization hint, which should do what you want, look for "is cached". But that is for a completely orthogonal kind of optimization. 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: Detecting side-effects in Perl 6 (Was: Re: infectious traits and pure functions)
HaloO, Daniel Ruoso wrote: Em Ter, 2009-02-17 às 09:19 -0300, Daniel Ruoso escreveu: multi infix:<+> (int where { 2 } $i, int where { 2 } $j) {...} As masak++ and moritz++ pointed out, this should be written multi infix:<+> (int $i where 2, int $j where 2) {...} Hmm, both these forms strike me as odd because the where clause should return a boolean and thus has to be written 'where { $_ == 2}'. The form above is true unconditionally! That is, it's identical to 'where {True}' which sort of is one way of writing Any. How should the generic where clause parser know to default to numeric equality? Through smart matching? Is that the default for a where clause with no operator? BTW, what is the supposed difference between these two forms? I would favour the first on the footing that the where clause belongs to the type. 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: The use of roles in S16 (Was: Re: r25328 - docs/Perl6/Spec)
Daniel Ruoso wrote: Maybe I'm thinking sideways again, but I haven't thought of "open" as being a method of any IO object, because usually "open" is the thing that gets you an IO Object. I'd expect the plain "open" to be really a sub (maybe a "is export" method in the generic IO role), that does whatever it needs to do to provide you an IO object, including composing the roles according to the features it supports. An important concept of testability is to decouple the use of objects from their creation. Global factory functions make testing harder. That said, in perl we can always override them, which would provide the necessary seam. One way of thinking about open is that it is a method on a file system object (or, more generally, on an IO server role): $fh = $*os.open($filename, :rw); $fh = $internet.open($url, :ro); ... Admittedly, that approach would tend to lead Perl down the road of Java, so it's probably good to have a global sub to hide the underlying details. It might seem even better be to introduce an object that represents the concept of an openable thing: $file = $file_system.find($filename); $fh = $file.open(:rw); However, file systems are very OS-dependent, so it is generally counterproductive to attempt to build a data structure that shadows a filesystem (e.g. what happens to $file if the underlying file is renamed?)
Re: IO, Trees, and Time/Date
On Tue, 2009-02-17 at 22:38 +1100, Timothy S. Nelson wrote: > My third thought is that it would be very useful also to have > date/time objects that integrate well with eg. ctime, mtime, and the like; > I'd > start with Time::Piece as a model. > > http://search.cpan.org/dist/Time-Piece/Piece.pm Conceptually, I agree. But there are places that Time::Piece assumes time is a sane thing, and it just isn't. Date::Time has a less DWIM interface, but is much more correct in the face of general human nuttiness on this topic (especially with regard to durations and timezones). I'd prefer to generally follow Date::Time, with DWIM features cherry picked from Time::Piece as long as they don't result in wrong behavior. (As an aside: It's the 21st century -- the default stringification of time objects should be easily parseable and sortable, not the insanity produced by Perl 5's 'scalar localtime'. ISO or SQL timestamp format please.) -'f
Re: Detecting side-effects in Perl 6 (Was: Re: infectious traits and pure functions)
TSa wrote: Daniel Ruoso wrote: The problem is that you can't really know wether a value is immutable or not, we presume a literal 1 to be immutable, but even if you receive :(Int $i), it doesn't mean $i is immutable, because that signature only checks if $i ~~ Int, which actually results in $i.does(Int). 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 and puts that into $i and also instructs the underlying object system to check for purity violation in the scope of the signature. The presence of this trait in methods called on $i and parameters $i is given to can be checked by the compiler. A save mode would be to allow only calls that have the trait. This is far from a halting problem. Simple coverage analysis suffices. I think in practice, unless Perl 6 is significantly updated, this really comes down to trust. We can do a lot of tests ahead of time, but in some respects an implementation shouldn't necessarily be forced to be immutable internally but rather would need to be trusted to externally do what it promises, which is provide a consistent unchanging snapshot at least during the course of a pure environment. I'm thinking specifically related to things like laziness or caching. If you have some Set doing objects and you want to, say, union them to produce another set, then fundamentally that is a pure operation on pure inputs. However internally said Set objects may perform some hashing of their elements to help determine uniqueness or equality and they may wait until the union is requested to calculate these; moreover, once calculated they probably want to cache that result for the next time someone does an operation that could benefit. Strictly speaking that cache is a mutation, at least unless you have some immutable value representing the whole cache and you derive another copy of the other version (mostly referring to the first plus delta for efficiency). In some ways we basically have to trust the programmer to supply code that does what they say it will, and if it doesn't then the program misbehaves and the programmer has to deal with it. This won't effect other people using Perl or our library etc that don't use that specific programmer's code. It mainly starts to be an issue if someone is executing code from someone else without examining the code first. This situation also seems similar to the idea of having private object attributes or what have you. If someone really wants to break the privacy they will, regardless of whether we have a closed unlocked door or a locked door. So to summarize, I think in order to make it easier for us to say write pure libraries that get what they expect (determinism, isolation, atomicity, etc) regardless of what users do, Perl itself will possibly need more enhancements to enforce that, and where those end, it comes down to trust. Like the limited warranty thing; it will perform correctly if you use it correctly. We can do input checks or whatever in our library, but after a point we're just doing these checks to give more meaningful error messages to users, and after a point if there is a failure on something we didn't check, then the users have to figure it out due to their improper input. And remember that by users I mean other programmer-written code in the same process as us, not external programs or human users. But in those cases we're not interacting by shared memory anyway, rather going by exchanges of undifferentiated bytes, so its not like they can pull tricks on us that normal proper input checking won't get. Getting purity right down to the point where you almost don't have to trust your users to do the right thing in order for you to do the right thing is a fundamental issue, and you almost have to design the system on a foundation of purity of pseudo-purity in order to get that, eg taking lessons from Haskell. As for working from where we are, well I like your snapshot idea, which is related to caching. If your declared parameter type is of an immutable type, then you snapshot your argument, a no-op if it actually is immutable, or otherwise what you actually snapshot is the result of invoking any operators on said argument, recursively on their results and so on ... its like memoization ... if the thing claims to be immutable then we can memoize any result from using it and just use that version afterwards rather than consulting the original. Where that works. multi infix:<+> (int where { 2 } $i, int where { 2 } $j) { say "The Big Brother is Watching You!" return 5; } Does a printout already constitute a side-effect? If so, it is at least not a dangerous one because it doesn't feed changed state back into the stream of a computation. The only danger is that a user wonders about the sequence of prints in the course of an optimized flow. IOW, sa
Re: IO, Trees, and Time/Date
On Tue, 17 Feb 2009, Richard Hainsworth wrote: Timothy S. Nelson wrote: Hi all. I know we usually run on forgiveness instead of permission, but I'm suggesting a big change (or extension, anyway), so I wanted to run the ideas by you all before I put the effort in. If I don't get feedback, I'll just make the changes. The first thing I wanted to suggest was that in S16, the OS-specific stuff be split out into separate roles. I suspect this is mostly non-controversial, so I'll do that unless someone complains. My second thought is that we need to specify tree objects (see http://www.mail-archive.com/perl6-language@perl.org/msg28579.html ). I'll put them in S16 unless someone complains. My third thought is that it would be very useful also to have date/time objects that integrate well with eg. ctime, mtime, and the like; I'd start with Time::Piece as a model. http://search.cpan.org/dist/Time-Piece/Piece.pm My final question is, since people are now getting somewhat familiar with the "file:" URI scheme (ie. file:/home/wayland/Notes.txt or file:/C/Documents and Settings/wayland/Notes.txt or whatever), I'm wondering if this isn't how we should be specifying our files; it's prettier than File::Spec :), and unified. Anyway, HTH, I like all the default suggestions. Not sure whether this means you completely agree with me, or completely disagree. It seems to me that a path, whether within a file system or across the internet, leads to a location. A location is a container for files. A file is a container for data. Given the strong typing paradigm of Perl6, it seems to me that the specification should distinguish between files and locations. It seems to me that unix blurs the difference between a file and a directory (at least readdir returns both file and directory names and the programer then needs a test to distinguish them), but that does not mean they are not conceptually different. I think you're confusing the inside and the outside of files. For me, the inside of a file is everything you can do to it when you've done an open (eg. read and write). The outside of a file is the other stuff (stat, chown, etc). Let me give you an example. Say I wanted to specify a path to a particular XML element, starting from the root of a filesystem. Say also, for argument's sake, that when the search path came to a file ending in .xml, it would, if there were children requested, read the file and dig through the tree. Then I could do something like this: /home/wayland/xml/foo.xml/html/head/title/text() Note that the directory called "xml" doesn't contain the file called "foo.xml". Instead, it contains a filesystem entry called "foo.xml". This filesystem entry in turn points to the contents (which I look at with an XML path). In other words, note the distinction between the *contents* of the file, and the entry in the file system that refers to it. Which is the file? Colloquially, both, but I'd argue that technically, the file is the *contents*, not the filesystem entry. For example, it is sensible to have a .files() method for a directory, but it is not sensible for such a method to exist for a file. Meanwhile, print/say/putc are not sensible for a directory/location. I'd argue that we want three things here, if we go down this path: IO::Dir.files() IO::FileNode.lines() IO::File.printf() However, it seems to me that maybe the .files() method is heading in the direction of PHPs 1001 string functions. It might be better like this: $dir = new IO::Dir("/home/wayland"); @files = grep { -f } @$dir; I know @$dir is bad perl6, but I hope you'll take the idea, in that, when we treat $dir as an array, we get a return of all children, whether files or directories, and then use -f to distinguish between them. Btw, the object creation line above could be done differently -- don't anyone get hung up on that. Moreover, if perl6 distinguishes between a location and a file, then the spec can distinguish between a .children() method that provides a list of child locations (viz., sub-directories) and .files(), which provides a list of the contents of the location. Keep in mind that files and directories are also not the only things in a filesystem. There are links, devices, pipes, and others to worry about. Which is why I prefer my solution. :) - | Name: Tim Nelson | Because the Creator is,| | E-mail: wayl...@wayland.id.au| I am | - BEGIN GEEK CODE BLOCK Version 3.12 GCS d+++ s+: a- C++$ U+++$ P+++$ L+++ E- W+ N+ w--- V- PE(+) Y+>++ PGP->+++ R(+) !tv b++ DI D G+ e++> h! y- -END GEEK CODE BLOCK-
Re: Detecting side-effects in Perl 6 (Was: Re: infectious traits and pure functions)
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.
r25371 - docs/Perl6/Spec
Author: wayland Date: 2009-02-18 04:30:33 +0100 (Wed, 18 Feb 2009) New Revision: 25371 Modified: docs/Perl6/Spec/S16-io.pod Log: S16: Redid things in terms of trees, at least somewhat. Modified: docs/Perl6/Spec/S16-io.pod === --- docs/Perl6/Spec/S16-io.pod 2009-02-17 21:05:38 UTC (rev 25370) +++ docs/Perl6/Spec/S16-io.pod 2009-02-18 03:30:33 UTC (rev 25371) @@ -204,21 +204,6 @@ the $.locale, or the undefined value at end of file, or if there was an error (in the latter case C<$!> is set). -=item our List multi method lines (IO $handle:) is export; - -=item our List multi lines (Str $filename); - -Returns all the lines of a file as a (lazy) List regardless of context. -See also C. - -=item our Item multi method slurp (IO $handle: *%opts) is export; - -=item our Item multi slurp (Str $filename, *%opts); - -Slurps the entire file into a Str or Buf regardless of context. -(See also C.) Whether a Str or Buf is returned depends on -the options. - =back =head2 IO::Writeable::Encoded @@ -314,19 +299,6 @@ =back -=head2 IO::FileDescriptor - -This role indicates that this object actually represents an open file -descriptor in the os level. - -=over - -=item method int fileno() - -File descriptors are always native integers, conforming to C89. - -=back - =head2 IO::Closeable This role indicates that this object can be closed. @@ -350,26 +322,17 @@ =head2 IO::Socket -role IO::Socket { +role IO::Socket { + has %.options; ... } +Accessing the %.options would on Unix be done with getsockopt/setsockopt. + =over -=item socket +=item pair -=item IO.setsockopt - -=item IO.shutdown - -(should IO::Socket.close() call shutdown, instead of having a different name?) - -=item IO.accept - -=item IO.bind - -=item Socket.pair - our List of IO method pair(Int $domain, Int $type, Int $protocol) A wrapper for socketpair(2), returns a pair of IO objects representing the @@ -381,18 +344,89 @@ =back -=head1 Filehandles, files, and directories +=head2 IO::Listening -=over 4 +=item open -=item IO.fcntl + method open() -Available only as a handle method. + Does a bind() and a listen(). -=item IO.ioctl +=item accept -Available only as a handle method. + method IO::Socket accept() +=head2 Tree Roles and Classes + +To support the filesystem, it is also useful to define some generic tree roles, which +could equally well be used for XML or LDAP as well as filesystem representation. However, +while the roles are generic, the comments and documentation in this section refers +specifically to filesystems. + +=head3 Tree::Name + + class Tree::Name { + has $.namespace; + has $.prefix; + + # Call this for stringifying + method fullname() + } + + fullname for XML does "$namespace:$prefix" + +=head3 Tree::Node + +This should be an ancestor role to filesystems, their elements, their attributes, and the +like. + + role Tree::Node does Array { + has Tree::Name $.name; # would usually be File or Directory on a filesystem + has $.ownerNode; # This is the IO::FileSystem + has $.rootNode; This is the root of the filesystem + has $.parent; # Another Tree::Node + has @.children handles ; # This is all the child notes + has $.path is ro; # Accessor does a getpath + has $.depth is ro; # depth from $ownerNode + + method infix:<===>(...) + method infix:<==>(...) + multi method *infix:(Tree::Node @nodes: Matcher $test); + multi method postfix:(Tree::Node @parents: Matcher $test); + method path(Str $.quitcriteria); # This allows the path call to quit eg. when it + # gets to the filesystem root, instead of the overall root + } + +Array operations on this are entirely capable of moving files and directories, + +=head3 Tree + + role Tree does Tree::Node { + has Tree::Node $root; # The root directory + has Tree::Node $cwn; # The current working directory (node) + } + +=head3 Tree::Element + + role Tree::Element does Tree::Node { + has %.attributes; # This is all the attributes, including Name + has Str $!defaultattributename; + method postcircumfix:<{ }>($selector, $node(s)); # Accesses stuff in %attributes + method pathelement(); + } + +=head3 Tree::Attribute + + role Tree::Attribute does Tree::Node { + has $.value; + +method pathelement(); + } + +=head1 Filehandles, files, and directories + +=over 4 + =item IO.name The C<.name> method returns the name of the file/socket/uri the handle @@ -442,40 +476,37 @@ =item IO.truncate +=item IO.fcntl + +Available only as a handle method. + =back =head2 IO::FileSystem This reads directories, deletes filesystem entries, creates links, and the like. -class IO::FileSystem does IO::Streamable { - has IO::FileSystemEntry $.cwd; # Current working directory - has IO::FileSystemEnt
Re: Detecting side-effects in Perl 6 (Was: Re: infectious traits and pure functions)
Something that may possibly be relevant to this discussion as an object lesson ... In the near future, probably next week, I'm going to re-implement the guts of my Set::Relation module (for Perl 5, on CPAN now), from an eagerly evaluated sometimes mutable or immutable object, to a often-lazily evaluated always immutable object. This is partly to help improve its performance but also to make it better in other ways. Other design changes will be made too, but I said the most significant one. That module will subsequently be translated to Perl 6. How this can be an object lesson is that it involves slightly complicated types and operators, all of which are conceptually pure, but which internally make use of hashing or caching for performance. Moreover, various user inputs to this module would be naturally mutable, eg inserting a Hash into a Set of Hash, but we don't want the Hash to mutate after being inserted into the Set; also the values of the Hash may be arbitrarily complex or any type, mutable or immutable. The laziness is partly done so that you can make the analogy of "%foo = $baz" work on an immutable %foo, having semantics like "%foo = {*%foo, :bar($baz)}" while still having good performance. (My "*%foo" means flatten foo, but that syntax is probably outdated.) There are other reasons. But I think we can use this as one early proof of concept or practical experimentation of how to handle matters of pure functions and handling side effects or what have you. After that Set::Relation is improved, then Muldis::Rosetta would then be implemented, doing that on a larger scale. -- Darren Duncan
r25373 - docs/Perl6/Spec
Author: wayland Date: 2009-02-18 06:09:25 +0100 (Wed, 18 Feb 2009) New Revision: 25373 Modified: docs/Perl6/Spec/S16-io.pod Log: S16: Started adding some DateTime stuff, but stopped pending some questions to the mailing list. Modified: docs/Perl6/Spec/S16-io.pod === --- docs/Perl6/Spec/S16-io.pod 2009-02-18 05:06:54 UTC (rev 25372) +++ docs/Perl6/Spec/S16-io.pod 2009-02-18 05:09:25 UTC (rev 25373) @@ -423,26 +423,167 @@ method pathelement(); } -=head1 Filehandles, files, and directories +=head2 Time and Date roles -=over 4 +=head3 Date -=item IO.name +You probably want to use the DateTime object instead. -The C<.name> method returns the name of the file/socket/uri the handle -was opened with, if known. Returns undef otherwise. There is no -corresponding C function. +role Date { + has Calendar $.calendar; + has NumberName $.year; + has NumberName $.month; + has NumberName $.dayofmonth; + has NumberName $.dayofweek; + has NumberName $.dayofyear; + has NumberName $.dayofquarter; + has NumberName $.quarter; + has NumberName $.era; # 'Common', 'Christian', etc + has Str $.defaultformat; -=item sysopen + method toString($format); + method isLeapYear(); -=item umask + multi method DateTime infix:<+>(Date $self, Time $other); + multi method DateTime infix:<+>(Date $self, Duration $other); -=item utime + multi method infix:<<=>>(Date $self, Date $other); + multi method infix:<<=>>(Date $self, Duration $other); + method get(Str $type, Str $of); + method last(Str $type, Str $of); +} + +Example: + +$date = new Date('2002/01/01'); +$date.month.name(); # January +$date.month.name('short'); # Jan +$date.get('day', of => 'year'); + +$date = new Date('2002/01/01'); +$date.convertcalendar('Chinese'); +$date.year.name(); # Snake + +A fair bit of initialisation of the NumberNames for day of the week and month will need to +be done. + +$format will naturally need to allow for eras. + +=over + +=item + + method toString($format = '/MM/DD'); + +$format contains things like /MM/DD or whatever. + =back +=head3 Time + +You probably want to use the DateTime object instead. + +role Time { + has $.hour; + has $.minute; + has $.second; + + method toString($format?); + # This can't be right; how do we specify this + multi method infix:<<=>>(Time $self, Time $other); + multi method infix:<<=>>(Time $self, Duration $other); +} + +When created, recognises "today" as a possibility. + =head1 Classes +=head2 Time and Date classes + +=head3 NumberName + + class NumberName { + has $.number; + + method name($format?) { + ... + } + } + +=head3 Timezone + +role Timezone { + has $.number; + + method name($format); + method is_dst(); +} + +=head3 DateTime + +class DateTime does Date does Time does Timezone { + has $.locale; + has $.parser; + has $.formatter; # Only for output formats + + multi method DateTime infix:<+>(DateTime $self, Duration $other); + + multi method infix:<->(DateTime $self, Duration $other); + multi method infix:<->(DateTime $self, Duration $other); + + multi method infix:<<=>>(DateTime $self, DateTime $other); + multi method infix:<<=>>(DateTime $self, Duration $other); + + method init(); + method truncate(Str $to); + method last(Str $type, Str $of); + method toString($format?); +} + +All formats are CLDR, although implementations may want to have another set of functions +that use the strftime functions instead. + +=over + +=item init + + method init(Str $String) # parser defaults to 'strptime' or something similar + | (Str $parser, Str $String) # $parser = 'strptime' + | (Str $parser, Int $Epoch) # $parser = 'epoch' + | (Str $parser, Str $Timezone?) # $parser = 'today' [unless strptime does this] + ; + +Tries to parse the date and time specified using $parser. + +If $Epoch is passed in instead, then it interprets the time as being in seconds since the +epoch (which is determined on a system-by-system basis). + +If $parser is 'today', then the current time is gotten. Timezone would be useful for +simulating eg. gmtime(). + +=item truncate + +Can be used to truncate a function to the current day, or whatever. + +=item last + + $date.last('day', of => 'month'); + +=back + +=head3 Duration + +=head3 Repetition + +This class specifies when a repetitive action (eg. a cron job) happens. + +class DateTime::Recurring { +... +} + +Should allow creation from the format that cron uses (ie. */5 * * * * ). + =head2 IO::File This does file input and output. @@ -961,6 +1102,18 @@ =over 4 +=item IO.name + +The C<.name> method returns the name of the file/socket/uri the ha
Re: IO, Trees, and Time/Date
On Tue, 17 Feb 2009, Geoffrey Broadwell wrote: On Tue, 2009-02-17 at 22:38 +1100, Timothy S. Nelson wrote: My third thought is that it would be very useful also to have date/time objects that integrate well with eg. ctime, mtime, and the like; I'd start with Time::Piece as a model. http://search.cpan.org/dist/Time-Piece/Piece.pm Conceptually, I agree. But there are places that Time::Piece assumes time is a sane thing, and it just isn't. Date::Time has a less DWIM interface, but is much more correct in the face of general human nuttiness on this topic (especially with regard to durations and timezones). I'd prefer to generally follow Date::Time, with DWIM features cherry picked from Time::Piece as long as they don't result in wrong behavior. Agreed, and that's kinda what I'm doing. But I still think there's room for improvement. 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. 2. Documents in terms of operator overloading 3. Depends a lot more on CLDR formats 4. Doesn't have multiple functions that perform exactly the same thing 5. As a consequence of all of the above, has a lot fewer functions (while still providing all the same functionality). (As an aside: It's the 21st century -- the default stringification of time objects should be easily parseable and sortable, not the insanity produced by Perl 5's 'scalar localtime'. ISO or SQL timestamp format please.) Fine by me. - | Name: Tim Nelson | Because the Creator is,| | E-mail: wayl...@wayland.id.au| I am | - BEGIN GEEK CODE BLOCK Version 3.12 GCS d+++ s+: a- C++$ U+++$ P+++$ L+++ E- W+ N+ w--- V- PE(+) Y+>++ PGP->+++ R(+) !tv b++ DI D G+ e++> h! y- -END GEEK CODE BLOCK-
Spec reorganisation
Hi all. I'd like to suggest a slight reorganisation within the specs. The first thing I've observed is that, in defining the IO stuff, and adding in the Tree and DateTime stuff, is that we're getting a lot of non-IO stuff in there. I'm aware that the numbering and ordering of the specs is based on the chapters in the Camel book. It seems like a lot of this stuff that I'm working on would really belong under 32: Standard Modules. But there's a lot of this stuff, and, while the Camel book just gives an overview of each module, we want to specify the API. I'm not suggesting here that we specify the interfaces to all the modules listed in the Camel book, or anything like that. Instead, I'm suggesting that the S32 space be used for documenting the objects that we don't seem to be able to get away from. My thought is that, at the moment, these are: - The function groups documented in S29 - The IO, Tree, and DateTime stuff being drafted in S16 After looking through the Phlanx project (which lists 100 or so top perl modules), and the list in the Camel book, I can only see one or two other things we might eventually need, and these can be worried about later. Anyway, my suggestion is that a folder called S32-standard-modules be created in the Spec directory, and that within this folder, the following files be created from the specified sources: - Tree.pod -- S16 - DateTime.pod -- S16 (needs lots of work) - IO.pod -- S16 - Most of the stuff from the S29 "Function Packages", in separate files This would leave S29 free to be solely a list of the functions that do not need to have a package specified when called, and can in most cases simply specify what standard library functions they call. It would also leave S16-IO free to deal with things that are not specific to the object(s). Thoughts? - | Name: Tim Nelson | Because the Creator is,| | E-mail: wayl...@wayland.id.au| I am | - BEGIN GEEK CODE BLOCK Version 3.12 GCS d+++ s+: a- C++$ U+++$ P+++$ L+++ E- W+ N+ w--- V- PE(+) Y+>++ PGP->+++ R(+) !tv b++ DI D G+ e++> h! y- -END GEEK CODE BLOCK-
Re: The use of roles in S16 (Was: Re: r25328 - docs/Perl6/Spec)
On 2009 Feb 16, at 22:44, Timothy S. Nelson wrote: So you can have a stream handle which does IO::Writeable, but will throw an error on any attempt to write? Anyway, you've answered my question in the other e-mail. Not sure what you're getting at, but the obvious example is a writeable handle on a full filesystem. I don't think we want Perl deciding to remove IO::Writeable because the fs happens to be full at the instant it's opened. -- 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 PGP.sig Description: This is a digitally signed message part
Re: IO, Trees, and Time/Date
Timothy S. Nelson wrote: Conceptually, I agree. But there are places that Time::Piece assumes time is a sane thing, and it just isn't. Date::Time has a less DWIM interface, but is much more correct in the face of general human nuttiness on this topic (especially with regard to durations and timezones). I'd prefer to generally follow Date::Time, with DWIM features cherry picked from Time::Piece as long as they don't result in wrong behavior. Agreed, and that's kinda what I'm doing. But I still think there's room for improvement. 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. 2.Documents in terms of operator overloading 3.Depends a lot more on CLDR formats 4.Doesn't have multiple functions that perform exactly the same thing 5.As a consequence of all of the above, has a lot fewer functions (while still providing all the same functionality). Talking about dates and times, I have some suggestions. First of all, I don't think that most DateTime stuff belongs in IO. The class definitions to represent a date or time or duration etc value, as well as operators to convert date formats etc or add/subtract etc dates are strictly internal, same as number or string operations. Only the routines to fetch the current system time and the like belong in IO, or routines concerning file timestamps etc. Second of all, I think a more generic term than DateTime should be used to name an object that represents an instant in time; for example I suggest calling it "Instant". The name "Instant" fits in a lot better in the company of other generic sounding temporal data types like "Duration" etc. Then, you can say that things like DateTime, Date, Time, etc are subtypes of Instant. See also http://search.cpan.org/dist/Muldis-D/lib/Muldis/D/Ext/Temporal.pod where I've specced out such matters, and that illustrates something I recommend for you. My Instant types very closely resemble both the Perl DateTime library as well as the SQL temporal types, which are actually very similar, though I've generalized it a bit. This spec explicitly does not support time zones (it has UTC or floating, that's it) and it doesn't include conversions with strings, but it has the foundation on which such could be built. And yours doesn't have to be the same of course. -- Darren Duncan
r25374 - docs/Perl6/Spec
Author: wayland Date: 2009-02-18 07:14:51 +0100 (Wed, 18 Feb 2009) New Revision: 25374 Modified: docs/Perl6/Spec/S16-io.pod Log: Bits and pieces, but mostly trying to clean up the list of unfiled functions. Modified: docs/Perl6/Spec/S16-io.pod === --- docs/Perl6/Spec/S16-io.pod 2009-02-18 05:09:25 UTC (rev 25373) +++ docs/Perl6/Spec/S16-io.pod 2009-02-18 06:14:51 UTC (rev 25374) @@ -430,7 +430,7 @@ You probably want to use the DateTime object instead. role Date { - has Calendar $.calendar; + has Calendar $.calendar; # Gregorian, Secular, Julian, etc has NumberName $.year; has NumberName $.month; has NumberName $.dayofmonth; @@ -694,9 +694,15 @@ class IO::FSNode does Tree::Node { has Array of IO::FSNodeACL @.ACLs; + has Hash of %.times; ... } +The %times has keys that can be eg. ctime, Modification, and Access (and maybe others on +other operating systems), and the values are all DateTime objects. + +When .path() is implemented, it should return the path that this was opened with. + =over 4 =item IO ~~ :X @@ -805,6 +811,16 @@ Test whether the specified filename is the same file as this file. On a Unix system, this would presumably be done by comparing inode numbers or something. +=item init + +This is called automatically on object creation; I'm unsure if init is the right name. + +multi method init(@pathelements); # new IO::FSNode('home', 'wayland') +multi method init(String $type, String $path) # new IO::FSNode('Unix', '/home/wayland'); +multi method init(String $path) # new IO::FSNode('/home/wayland'); + +This last throws an error if "use portable" is used. + =back =head2 IO::FSNodeACL @@ -1102,20 +1118,6 @@ =over 4 -=item IO.name - -The C<.name> method returns the name of the file/socket/uri the handle -was opened with, if known. Returns undef otherwise. There is no -corresponding C function. - -=item sysopen - -=item umask - -=item utime - -=item IO.fileno - =item IO.ioctl Available only as a handle method. @@ -1126,10 +1128,16 @@ our Str prompt (Str $prompt) +Should there be an IO::Interactive role? + =item Str.readpipe +=item sysopen + =item IO.sysseek +=item umask + =back =head1 Removed functions @@ -1140,6 +1148,18 @@ Gone, see IO::Endable +=item IO.fileno + +See IO::FileDescriptor + +=item IO.name + +Changed to .path(), but we haven't gotten around to specifying this on all of them. + +The C<.name> method returns the name of the file/socket/uri the handle +was opened with, if known. Returns undef otherwise. There is no +corresponding C function. + =item pipe Gone, see Pipe.pair @@ -1164,6 +1184,10 @@ Gone, see IO::Writeable.read() +=item utime + +Gone, see %IO::FSNode.times. + =back =head1 Additions
Re: IO, Trees, and Time/Date
On Tue, 17 Feb 2009, Darren Duncan wrote: Talking about dates and times, I have some suggestions. First of all, I don't think that most DateTime stuff belongs in IO. The class definitions to represent a date or time or duration etc value, as well as operators to convert date formats etc or add/subtract etc dates are strictly internal, same as number or string operations. Only the routines to fetch the current system time and the like belong in IO, or routines concerning file timestamps etc. I agree they don't belong in that part of the spec; I've just written another e-mail about that ("Spec reorganisation"). Second of all, I think a more generic term than DateTime should be used to name an object that represents an instant in time; for example I suggest calling it "Instant". The name "Instant" fits in a lot better in the company of other generic sounding temporal data types like "Duration" etc. Then, you can say that things like DateTime, Date, Time, etc are subtypes of Instant. Love the name; I'll do the rename as soon as the Spec reorganisation is sorted out. It also means that we can use DateTime to refer to Instant+Duration+... :). See also http://search.cpan.org/dist/Muldis-D/lib/Muldis/D/Ext/Temporal.pod where I've specced out such matters, and that illustrates something I recommend for you. My Instant types very closely resemble both the Perl DateTime library as well as the SQL temporal types, which are actually very similar, though I've generalized it a bit. This spec explicitly does not support time zones (it has UTC or floating, that's it) and it doesn't include conversions with strings, but it has the foundation on which such could be built. And yours doesn't have to be the same of course. I'll look into it :). Thanks, - | Name: Tim Nelson | Because the Creator is,| | E-mail: wayl...@wayland.id.au| I am | - BEGIN GEEK CODE BLOCK Version 3.12 GCS d+++ s+: a- C++$ U+++$ P+++$ L+++ E- W+ N+ w--- V- PE(+) Y+>++ PGP->+++ R(+) !tv b++ DI D G+ e++> h! y- -END GEEK CODE BLOCK-
r25375 - docs/Perl6/Spec
Author: wayland Date: 2009-02-18 07:29:03 +0100 (Wed, 18 Feb 2009) New Revision: 25375 Modified: docs/Perl6/Spec/S16-io.pod Log: Fixed operator overloading calls. Modified: docs/Perl6/Spec/S16-io.pod === --- docs/Perl6/Spec/S16-io.pod 2009-02-18 06:14:51 UTC (rev 25374) +++ docs/Perl6/Spec/S16-io.pod 2009-02-18 06:29:03 UTC (rev 25375) @@ -447,8 +447,8 @@ multi method DateTime infix:<+>(Date $self, Time $other); multi method DateTime infix:<+>(Date $self, Duration $other); - multi method infix:<<=>>(Date $self, Date $other); - multi method infix:<<=>>(Date $self, Duration $other); + multi method infix:{'<=>'}(Date $self, Date $other); + multi method infix:{'<=>'}(Date $self, Duration $other); method get(Str $type, Str $of); method last(Str $type, Str $of); @@ -491,8 +491,8 @@ method toString($format?); # This can't be right; how do we specify this - multi method infix:<<=>>(Time $self, Time $other); - multi method infix:<<=>>(Time $self, Duration $other); + multi method infix:{'<=>'}(Time $self, Time $other); + multi method infix:{'<=>'}(Time $self, Duration $other); } When created, recognises "today" as a possibility. @@ -532,8 +532,8 @@ multi method infix:<->(DateTime $self, Duration $other); multi method infix:<->(DateTime $self, Duration $other); - multi method infix:<<=>>(DateTime $self, DateTime $other); - multi method infix:<<=>>(DateTime $self, Duration $other); + multi method infix:{'<=>'}(DateTime $self, DateTime $other); + multi method infix:{'<=>'}(DateTime $self, Duration $other); method init(); method truncate(Str $to);
Re: IO, Trees, and Time/Date
Timothy S. Nelson wrote: On Tue, 17 Feb 2009, Darren Duncan wrote: Second of all, I think a more generic term than DateTime should be used to name an object that represents an instant in time; for example I suggest calling it "Instant". The name "Instant" fits in a lot better in the company of other generic sounding temporal data types like "Duration" etc. Then, you can say that things like DateTime, Date, Time, etc are subtypes of Instant. Love the name; I'll do the rename as soon as the Spec reorganisation is sorted out. Great to hear. It took me a bit of effort back in September to come up with it. And by the way, potentially another good word would have been Moment except that this word is often used by physics people to mean either of several different things than an instant in time. Instant didn't seem to have that problem of there being possibly confused other uses. It also means that we can use DateTime to refer to Instant+Duration+... :). You could. Or why not use "Temporal" if you want a broader category or namespace? That's the most generic term I can think of that accurately applies and that it would be easy for people to understand at a moment's glance. (It is also a lot easier to think up in the first place than Instant but was too broad for the latter's use.) And using single word names for things where they fit is a lot more elegant I think, and is also in keeping with the Perl way of built-ins tending to all have single word names. Save "Date" and "Time" for more specific things rather than more general things. Also, calling something "DateTime" smells, like it was a fall-back because it was difficult to come up with a single word. It smells like having a numeric type and calling it "WholeFraction" rather than "Number" or "Rational". Thank you. -- Darren Duncan