Re: DBI v2 - The Plan and How You Can Help

2005-07-05 Thread Sam Vilain

Darren Duncan wrote:
Okay, considering that using the same name prepare() like this may 
confuse some people, here is a refined solution that uses 3 methods 
instead; please disregard any contrary statements that I previously made:


I think I'm beginning to like it.

Allow me to suggest one or two further refinements...


  # Opt 1: A user that wants the most control can do this (new feature):

  my $sth1 = $dbh.compile( $sql_or_ast ); # always sans connection
  $sth1.prepare(); # always with connection, even if DBD doesn't use it
  $sth1.execute(); # always with connection


To me, the compiled form of the STH is related to the driver, but
re-usable between connections; you should be able to use something like;

  my $sth1 = DBD::SQLite.compile( $sql_or_ast );
  $sth1 = DBI.compile( :statement($sql_or_ast), :driverSQLite );

This would give you a STH which is divorced from the actual DB connection
instance.  Because you constructed it like this, without reference to a
(possibly unconnected) connection object, then $sth1.prepare is not
available.

You'd then need to use something like;

  $sth1.prepare($dbh);
  $dbh.prepare($sth1);

Note I also think what you wrote should work, too.

The new feature is if you decide to use compile(); you then give that 
method the arguments you would have given to prepare(), and you invoke 
prepare() on the result with no arguments; each DBD would decide for 
itself how the work is divided between compile() and prepare() with the 
limitation that compile() is not allowed to access the database; ideally 
the DBD would place as much work there as is possible, which would vary 
between Oracle/Pg/etc.


Agreed.


In particular, I don't think that the DB driver should automatically
get a chance to interfere with SQL::Statement; if they want to do that,
then they should specialise SQL::Statement.  IMHO.
I am operating under the assumption here that while the new DBI is 
designed to effectively support wrapper modules, the wrapper modules 
would also be altered from their current DBI-1-geared designs to 
accomodate DBI-2.

But still, what do you mean by interfere?


Well, when you parse the statement into an AST, the flavour of SQL will
affect how it is parsed and what is allowed.  Eg, Oracle has significant
features in some comments (query hints).  It also has quirky and somewhat
useless keywords like CONNECT BY.

So, when you ask a DBH connected to a driver to parse something, then it
will use that driver's SQL dialect, if one exists, but I still want to be
able to deal with SQL ASTs without implying a SQL flavour.


Either way, you don't want most applications dealing with this complexity
at all, really.
I am operating under the assumption that this system should work if 
there are no external config files that the DBI/DBD would read, and the 
application would provide that information; if its in a file, the 
application would read it in, or would explicitly tell DBI where it is.  
Or at least it should be possible for this to happen, even if a DBD 
defaults to look in a default location when it doesn't get the 
equivalent from the application.


Absolutely, that must work.  But it would still be nice to be able to
config this without digging through the application to see where the
password is written.

Unless there is a design flaw in DBI, we should not have to update that 
module just because a new driver came into existence whose name has not 
yet been hard-coded into DBI.

See this block for example, from DBI.pm v1.48:
 my $dbd_prefix_registry = {
  ad_  = { class = 'DBD::AnyData',},

  [...]

  yaswi_   = { class = 'DBD::Yaswi',},
 };
I mean, what's up with that?  I assume DBI 1 has this for legacy app 
backwards compatability, but DBI version 2 should never have to 
accomodate such abhorrent computer programming practices in its core.


Such a great word, abhorrent.  So fitting for this case.  It sure does
look like an (overprematuremisguided)-optimisation to avoid using the
full module name in an internal hash or something like that.  But then
maybe (Iwenone(Gaia)) are missing some context there.

Sam.


Re: DBI v2 - The Plan and How You Can Help

2005-07-05 Thread Adam Kennedy
4. All host parameters should be named (like :foo) rather than 
positional (like ?), meeting with the SQL:2003 standard.  The named 
format is a lot easier to use and flexible, making programmers a lot 
less error prone, more powerful, and particularly more resource 
efficient when the same parameter is conceptually used multiple times in 
a SQL statement (it only has to be bound once).  If anyone wants to use 
positional format, it could easily be emulated on top of this. Or, if 
native positional support is still important, then it should be a 
parallel option that can be used at the same time as named in any 
particular SQL statement.  See the native API of SQLite 3 for one 
example that (I believe) supports both in parallel.  This also means 
that execute() et al should take arguments in a hash rather than an array.


Yes, native positional support is still important.

positions make it very easy to do SQL math.

To express it in overly simplistic code

$foo = [ a = ?, foo ];
$bar = [ b = ?, bar ];

$baz = $foo and $bar;
# $baz now is [ a = ? and b = ?, foo, bar ];

Bearing mind a situation with an arbitrary number and complexity of 
these sql fragments to be added together, doing this sort of thing using 
named placeholders would be a nightmare.


and we'd just end up with every second person implementing a ? to :p1, 
:p2 scheme in their database layers. If you want positional 
placeholders, it needs to be an additional feature, not a replacement 
for positional placeholders.




Re: DBI v2 - The Plan and How You Can Help

2005-07-05 Thread Darren Duncan

At 6:14 PM +1200 7/5/05, Sam Vilain wrote:

I think I'm beginning to like it.
Allow me to suggest one or two further refinements...


  my $sth1 = $dbh.compile( $sql_or_ast ); # always sans connection
  $sth1.prepare(); # always with connection, even if DBD doesn't use it
  $sth1.execute(); # always with connection


FYI, I'm not stuck on the name 'compile'; the method could be called 
something else.  In fact, I still think 'prepare' is more broadly 
descriptive considering the wide range of things that could be 
happening inside that method; I see it as ultimately getting ready 
for the execute() anyway.  The problem is that the word 'prepare' is 
commonly associated with something different, so we're stuck having 
to find a different word.



To me, the compiled form of the STH is related to the driver, but
re-usable between connections; you should be able to use something like;

  my $sth1 = DBD::SQLite.compile( $sql_or_ast );
  $sth1 = DBI.compile( :statement($sql_or_ast), :driverSQLite );

This would give you a STH which is divorced from the actual DB connection
instance.


Yes, that is true.  However, I like for all application calls to go 
through the Interface module (DBI) since that is what the Interface 
is for.  It is also more practical to go by way of the DBI module 
because it can do things for you like certain kinds of validation on 
application input and driver output, so the application or driver 
respectively doesn't have to do those tests for robustness.  Each DBI 
driver can worry less about that its input is correct and focus more 
on its actual work.  (FYI, a common input/output validation is one of 
the main things that the 'Rosetta' module does for its own drivers 
and users.  More so in next release v0.46.)



Because you constructed it like this, without reference to a
(possibly unconnected) connection object, then $sth1.prepare is not
available.


I wouldn't worry about that; the proposed DBI would elegantly handle 
(throw an exception) attempts to invoke methods that depend on an 
open connection when there is none.  People who like to check first 
will also have a $dbh.is_open() method available to them.  I also see 
the situation as no worse than the current DBI v1 where you can 
invoke such things as fetchrow_arrayref() on a $sth that hasn't been 
executed yet.


Oh, and I have another DBI v2 suggestion to add, also following Rosetta design:

1. A $sth should not contain any methods for fetching the result of 
an executed statement; rather, execute() should return an object when 
successful that represents its result; you invoke fetching methods on 
that object.  For example:


  my $rlh = $sth-execute();
  my $rowset = $rlh-fetchrow_arrayref();

This approach is a lot more flexible.


Well, when you parse the statement into an AST, the flavour of SQL will
affect how it is parsed and what is allowed.  Eg, Oracle has significant
features in some comments (query hints).  It also has quirky and somewhat
useless keywords like CONNECT BY.

So, when you ask a DBH connected to a driver to parse something, then it
will use that driver's SQL dialect, if one exists, but I still want to be
able to deal with SQL ASTs without implying a SQL flavour.


You still can.  The point of an abstract syntax tree is that the 
original SQL dialect isn't very important to what it contains (and 
this is how SQL::Routine is); by contrast, a concrete syntax tree 
cares very much about the original syntax and preserves it to the 
last detail.  I don't see a problem here.

...
Except that those AST-like-modules which embed raw SQL fragments 
(like where-clauses) as a matter of course aren't actually that 
abstract and could pose a problem; lots of DBI wrappers are this way, 
unfortunately (but not mine).


I am operating under the assumption that this system should work if 
there are no external config files that the DBI/DBD would read, and 
the application would provide that information; if its in a file, 
the application would read it in, or would explicitly tell DBI 
where it is.  Or at least it should be possible for this to happen, 
even if a DBD defaults to look in a default location when it 
doesn't get the equivalent from the application.


Absolutely, that must work.  But it would still be nice to be able to
config this without digging through the application to see where the
password is written.


Er, I hope you didn't interpret this as the application source code. 
My point was that the database connection details can be part of the 
general application configuration file, which is still data and not 
code.  This way, each application can have distinct database settings 
if it wants to.



Such a great word, abhorrent.  So fitting for this case.  It sure does
look like an (overprematuremisguided)-optimisation to avoid using the
full module name in an internal hash or something like that.  But then
maybe (Iwenone(Gaia)) are missing some context there.


Well, I have also decided that I can 

Re: DBI v2 - The Plan and How You Can Help

2005-07-05 Thread Adam Kennedy

  - optional treatment of the statements as an AST, similar in concept to
SQL::Routine, or Tangram::Expr.  Death to SQL templating systems!


I suspect during this process people are going to want a lot of things 
that layer on top of what we currently see as DBI.


Personally I think Tim got it right to initially only handle 
connectivity and preparation stuff in DBI, and not try to deal with 
schemas or relational-mapping or any of that other gumpf.


I see the issues with the table methods in DBI as an example of this. 
What you want in many situations is something much more details that 
just a list of table names.


So with that in mind.

I'd like to see DBI done as a set of multiple interfaces that each 
driver can choose to support or not support.


For example, the connectivity layer. This currently works very very well 
and has allowed huge numbers of different interfaces to almost every 
database in existance.


Every driver, as they do now, should implement support for this layer.

On top of that, if you really must interact with the database to query 
table names and so on, lets see that done as a separate layer.


DBI2::Schema or something. drivers could then specifically advertise 
support or non-support for that API.


And we could get an interface somewhat richer than the current raw 
hashes one.


Adam K


Re: DBI v2 - The Plan and How You Can Help

2005-07-05 Thread Maxim Sloyko

Sam Vilain wrote:


However, making it in a file in $HOME/.xxx means that the sysadmin can
set it up to be mode 400 or something like that, to ensure other users
can't access it if someone forgot to set the permissions right on the
application code (or, hopefully, configuration file).



I don't think this solves the problem, because what I usually want is 
the user to be able to use the application, but unable to see the DB 
password. So the user should have read permission set for the file, 
but on the other hand he shouldn't. It's not not a problem for Web App, 
though.


--
Maxim Sloyko


Time::Local

2005-07-05 Thread Gaal Yahas
I've added localtime to pugs (r5233, 5236), to address Dave Rolsky's needs
for DateTime; but I'm noticing S29 doesn't spec this and nearby builtins
yet. I'd like to raise the questions I encountered / stipulations I've
made. Please let me know if I'm in error or update S29 if I am not.

Regarding Time::Local fields, it's an object now, so the order of things
matters less now than it did in p5. The fields I've made available
naturally follow GHC's CalendarTime type[1]. The important deviations
from p5 are:

 * .year is the Gregorian year, no 1900 offeset or anything like that.

   (Haskell doesn't promise accuracy in the readable version of
   pre-Gregorian dates, which I think is okay for us as well, as long
   as the opaque internal representation remains consistent. That's part
   of where libraries such as DateTime can help.)

 * .month and .wday are one-based. Sunday == 1. Haskell has them as
   enums which avoids off-by one confusion completely; I made them like
   I did because that's like humans think of them.

 * .picoseconds - we don't promise this granularity is available by the
   system, but I don't suppose we'll ever need anything finer than that
   :-)

 * Once we sort out context and want in pugs, I can return a List when
   one is expected, instead of an object. Then the order of fields
   becomes important and I'm inclined to go with year first, like the
   Haskell module, so that least significant things come last. This is the
   reverse of p5 Time::Local. When timelocal and timegm are implemented,
   they will of course use whatever order their inverses use.

As for the function signatures:

   multi sub localtime(Rat $?when = time) returns Time::Local { ... }
   multi sub localtime(Int $sec, Int ?$pico = 0) returns Time::Local {...}

The first form uses the second, but might be less precise.

[1] 
http://haskell.org/ghc/docs/latest/html/libraries/base/System.Time.html#t%3ACalendarTime

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


Re: Time::Local

2005-07-05 Thread Larry Wall
On Tue, Jul 05, 2005 at 04:39:48PM +0300, Gaal Yahas wrote:
: As for the function signatures:
: 
:multi sub localtime(Rat $?when = time) returns Time::Local { ... }
:multi sub localtime(Int $sec, Int ?$pico = 0) returns Time::Local {...}
: 
: The first form uses the second, but might be less precise.

I don't think either of those are good human engineering.  I would
like the preferred Perl 6 form to simply be:

multi sub localtime(Num $?when = time) returns Time::Local { ... }

The time function always returns the time in floating point.  In fact,
all numeric times are Num in Perl 6.  Then you don't have to worry
about whether picosecond resolution is good enough.  Time and
duration objects can, of course, do whatever they like internally,
and among themselves, but someone who says sleep($PI) should get a
$PI second sleep.  Our computers are capable of floating point these
days, and I consider any other numeric time format to be cultural
baggage.  I particularly loathe any kind of two integer format.

Sorry about the rant, but you seem to have pushed one of my hot buttons...

Larry


Re: Time::Local

2005-07-05 Thread Gaal Yahas
On Tue, Jul 05, 2005 at 08:16:54AM -0700, Larry Wall wrote:
 I don't think either of those are good human engineering.  I would
 like the preferred Perl 6 form to simply be:
 
 multi sub localtime(Num $?when = time) returns Time::Local { ... }

Done.

I take it that the rest is okay? If so I'll submit a doc patch to S29.

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


Re: Time::Local

2005-07-05 Thread Gaal Yahas
On Tue, Jul 05, 2005 at 11:41:23AM -0500, Dave Rolsky wrote:
 Regarding Time::Local fields, it's an object now, so the order of things
 
 Should that be Time::localtime?  In P5 there are Time::localtime  
 Time::gmtime, which are thin OO facades over the language builtins.  Then 
 there's the module Time::Local, which is entirely different.
 
Hmm, I agree. I used Time::Local because that's what the draft Synopsis
put them in, but Time is a better fit.

 All of those provide useful functionality, and probably Time::Local should 
 be part of the language, _or_ localtime  gmtime should be in a library.

Not my call, but I think we can add timelocal and timegm soon. They're
mostly cleverly-caching facades to Time.new anyway, no? Drop by on #perl6
if you want to hack on the Prelude side of this.

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


Re: Time::Local

2005-07-05 Thread Dave Rolsky

On Tue, 5 Jul 2005, Gaal Yahas wrote:


Regarding Time::Local fields, it's an object now, so the order of things


Should that be Time::localtime?  In P5 there are Time::localtime  
Time::gmtime, which are thin OO facades over the language builtins.  Then 
there's the module Time::Local, which is entirely different.


All of those provide useful functionality, and probably Time::Local should 
be part of the language, _or_ localtime  gmtime should be in a library.



* .year is the Gregorian year, no 1900 offeset or anything like that.


Yes!


* .month and .wday are one-based. Sunday == 1. Haskell has them as
  enums which avoids off-by one confusion completely; I made them like
  I did because that's like humans think of them.


And yes again!


* .picoseconds - we don't promise this granularity is available by the
  system, but I don't suppose we'll ever need anything finer than that
  :-)


The more granularity the better, really.  DateTime right now supports 
nanoseconds, which was a semi-arbitrary choice that seemed granular 
enough.  Picoseconds is even better.  Anyone who needs more probably has 
some sort of special hardware providing their data anyway, and will need a 
special interface to it (hand waving).



* Once we sort out context and want in pugs, I can return a List when
  one is expected, instead of an object. Then the order of fields
  becomes important and I'm inclined to go with year first, like the
  Haskell module, so that least significant things come last. This is the
  reverse of p5 Time::Local. When timelocal and timegm are implemented,
  they will of course use whatever order their inverses use.


I'd agree that this makes the most sense.


-dave

/*===
VegGuide.Orgwww.BookIRead.com
Your guide to all that's veg.   My book blog
===*/


Re: Time::Local

2005-07-05 Thread Dave Whipp

Larry Wall wrote:


The time function always returns the time in floating point.


I don't understand why time() should return a numeric value at all. 
Surely it should return a DateTime (or Time) object. Using epochs in a 
high level language seems like a really bad thing to be doing. If I want 
duration since epoch then I should subtract the epoch from the time -- 
resulting in a duration (which may indeed be a floating point value).


  my DateTime $epoch is constant = DateTime 2000-01-01 00:00:00;
  my Num $seconds_since_epoch = time - $epoch;


 In fact,
 all numeric times are Num in Perl 6.  Then you don't have to worry
 about whether picosecond resolution is good enough.  Time and
 duration objects can, of course, do whatever they like internally,
 and among themselves, but someone who says sleep($PI) should get a
 $PI second sleep.

For the sleep function, it seems reasonable to accept either a DateTime 
or a Duration, which would sleep either until the requested time, or for 
the requested duration.



Sorry about the rant, but you seem to have pushed one of my hot buttons...


Ditto


Larry


Re: Time::Local

2005-07-05 Thread Ingo Blechschmidt
Hi,

Dave Whipp wrote:
 Larry Wall wrote:
 The time function always returns the time in floating point.
 
 I don't understand why time() should return a numeric value at all.
 Surely it should return a DateTime (or Time) object. Using epochs in a
 high level language seems like a really bad thing to be doing. If I
 want duration since epoch then I should subtract the epoch from the
 time -- resulting in a duration (which may indeed be a floating point
 value).

FWIW, I agree, but I'd like to propose standard overloadings:
  my $time = time;# some kind of Date/Time object
  say ~$time; # Di 05 Jul 2005 20:01:42 CEST
  say +$time; # seconds since the Perl 6 epoch
  # (2000-01-01 according to [1])

 For the sleep function, it seems reasonable to accept either a
 DateTime or a Duration,

or a number of seconds,

 which would sleep either until the requested time, or for the
 requested duration.


--Ingo

[1]
http://groups.google.de/group/perl.perl6.internals/msg/a572113dc089481b

-- 
Linux, the choice of a GNU | Elliptic paraboloids for sale.  
generation on a dual AMD   | 
Athlon!| 



Re: Time::Local

2005-07-05 Thread Juerd
Dave Rolsky skribis 2005-07-05 11:41 (-0500):
 * .month and .wday are one-based. Sunday == 1. Haskell has them as
   enums which avoids off-by one confusion completely; I made them like
   I did because that's like humans think of them.
 And yes again!

No. Humans don't USE numbers for week days! So beginning at 1 makes no
sense, except for humans who like creating lists like (undef, Sunday
Monday ...). In fact, I would prefer Saturday Sunday Monday ... to
not having any 0 :)

Now, for months, yes it does make lots of sense.


Juerd
-- 
http://convolution.nl/maak_juerd_blij.html
http://convolution.nl/make_juerd_happy.html 
http://convolution.nl/gajigu_juerd_n.html


Re: Time::Local

2005-07-05 Thread Ingo Blechschmidt
Hi,

Juerd wrote:
 Ingo Blechschmidt skribis 2005-07-05 20:08 (+0200):
 FWIW, I agree, but I'd like to propose standard overloadings:
   say ~$time; # Di 05 Jul 2005 20:01:42 CEST
 
 Or perhaps not. In fact, rather not. Please let stringification be the
 ISO standard, and otherwise certainly sortable: year first, then
 month, then mday.
 
 2005-07-05T20:01:42+0200

WRT to sorting: The Date/Time/whatever class should overload
infix:«=», so sorting really works -- if you sort those ISO strings,
you'll probably get wrong results, as the timezone diff isn't taken
into account.

I don't have a strong opinion on the default format of the
stringification.

Could/should we use .as for this, to leave the choice to the programmer?

  say time.as(%H:%M:%S);   # 20:26:36

Note though that it's inconsistent:
  say hi.as(%H:%M:%S);   # error
  say time.as(%H:%M:%S);   # works


--Ingo

-- 
Linux, the choice of a GNU | The future is here. It's just not widely
generation on a dual AMD   | distributed yet. -- William Gibson  
Athlon!| 



Re: Time::Local

2005-07-05 Thread Douglas P. McNutt
At 10:55 -0700 7/5/05, Dave Whipp wrote:
I don't understand why time() should return a numeric value at all.

Some of us like to use epoch time, as an integer, to create unique file names 
which sort right in a shell or GUI.

-- 

-- From the U S of A, the only socialist country that refuses to admit it. --


Re: Time::Local

2005-07-05 Thread Dave Whipp

Douglas P. McNutt wrote:

At 10:55 -0700 7/5/05, Dave Whipp wrote:


I don't understand why time() should return a numeric value at all.


Some of us like to use epoch time, as an integer, to create unique file names which sort 
right in a shell or GUI.



You can use {time - $epoch} or {time.as%d} or {int time}. (That 
last one is not {+time}, because that would be a floating-point value, 
not an integer).


Re: Time::Local

2005-07-05 Thread Darren Duncan

All,

In the spirit of forward thinking and adaptability (and 
internationalization), I believe a core Time/Date object should be 
calendar agnostic and simply store some value that is easily 
convertable to any date + time on any calendaring system.  I say 
forward thinking because this system will be forwards compatible with 
calendaring systems that don't yet exist, and backwards compatible 
with older calendars we haven't bothered to account for yet.


I believe that at its core said object should simply store a count of 
rigorously defined time units relative to a rigorously defined epoch. 
What the epoch is and what the time unit is will need to be 
officially defined (eg, Jan 1, 2000; counting in fractions of 
seconds).  The object should not store anything other than this 
single numerical value internally (smart caching of conversions 
aside).


Save all human-desired representations to something that is computed 
on request, such as using a getter method named after the desired 
format; and setting would do the reverse.  This can work with values 
in any calendaring system.


With this system, date calculations and storage are trivially easy, 
and Perl's built-in date/time function would simply return that 
number or said object.  All the complexity is in the getter/setter 
methods that are specific to what details a user wants, such as the 
day of week or an ISO formatted string.  In fact, all of that actual 
conversion stuff would be what modules are good for.  Perl internally 
just has to know about the one number.


-- Darren Duncan


Re: Time::Local

2005-07-05 Thread Dave Whipp

Darren Duncan wrote:
The object 
should not store anything other than this single numerical value 
internally (smart caching of conversions aside).


I think we can all either agree with that, or dont-care it. The internal 
implementation is an implementation issue (or library). It doesn't need 
to be defined by the language. The one important thing is that that 
language shouldn't define semantics that require more than this single 
value (e.g. we shouldn't associate the epoch with the object).


Re: Time::Local -- and lexical scope

2005-07-05 Thread Dave Whipp

Dave Whipp wrote:

You can use {time - $epoch} or {time.as%d} or {int time}. (That 
last one is not {+time}, because that would be a floating-point value, 
not an integer).


I was thinking: an epoch is just a time, and int time is a duration -- 
the number of seconds since the current epoch. So, the following should 
work:


for 1 .. 2 - {
   use epoch time();
   sleep 6;
   say int time;
}

This should print something close to 6, twice.

But something niggled me: does the value of the RHS of a use get 
evaluated at run time, or compile time? In perl5, that could definitely 
would only execute the Cuse once.


I could see 3 possible behaviors:

1. Cuse sets the epoch for each iteration of the loop, thus calling 
time() one per iteration


2. Cuse executes just once, at compile time. Thus seconds iteration 
prints approximately 12


3. Cuse does a compile-time binding of the epoch to the time() 
function. So each iteration prints 0.



Which actually happens?


Re: Time::Local

2005-07-05 Thread Darren Duncan
Actually, there was a big oversight in my last message.  It does not 
handle approximate or relative dates, such as when you don't know the 
details.


My previous proposal should be restricted specifically to the 
situations where you know the date/time to a high precision, to the 
second.  So my previous proposal would still work for general tasks 
where the date/time you are storing in the object is generated by a 
clock, such as the computer's clock or a network time server etc, and 
is perfectly appropriate for what Perl's built-in get current 
date/time returns.


I should also clarify that when I say rigorously defined epoch, 
that also specifies a location (such as, Jan 1, 2000, at Greenwich 
(sp?)).  Any mess related to time zones would be accounted for only 
during any calendar conversion used for storage or retrieval.


For the other side, where the dates are imprecise, it actually would 
be useful to store them internally in calendar specific and human 
terms, basically matching whatever the source was.  For example, you 
would store a date/time like early May of 1743 this way; if all you 
know is that the date was in early May, then what you're storing is 
fully accurate.  Shoe-horning this into a specific day etc just for 
storage makes the data less accurate because someone reading the 
storage value presumes we knew for sure it was that day etc when in 
fact we didn't.  Another example of an imprecise and relative date is 
in the 4th year of Xerxes reign.  If you didn't know when on our 
calendar that Xerxes ruled, you can't exactly convert this to a 
Gregorian calendar; you must store it in the terms that I mentioned 
for highest accuracy.


Now of course, for such imprecise things, the simplest storage method 
is to just use a character string.  Where it gets more complicated is 
if you want to do math or calculations with this imprecise info; 
that's one place that date/time such modules would really be useful 
and have their work cut for them.


BTW, my main programming project (unreleased) is a 
genealogy/history/anything database type application, of an 
unprecedented focus and feature set, so I've thought a lot about 
these sorts of issues for being the most accurate and trustworthy 
possible.


-- Darren Duncan


Re: Time::Local

2005-07-05 Thread Craig DeForest

Quoth Darren Duncan on Tuesday 05 July 2005 04:20 pm,
 I believe that at its core [the time/date] object should simply store a 
count of
 rigorously defined time units relative to a rigorously defined epoch.
 What the epoch is and what the time unit is will need to be
 officially defined (eg, Jan 1, 2000; counting in fractions of
 seconds).  The object should not store anything other than this
 single numerical value internally (smart caching of conversions
 aside).


Agree agree...

Hmmm  Straight seconds-counting has the flavor of international atomic 
time (TAI) to it, which suggests using the TAI (rather than UNIX) epoch.

Using the TAI epoch of 1958-01-01 00:00:00 has several advantages:
- TAI is recognized by international standards-setting bodies (BIPM).
- Perl6 will then shake out the 31-bit time rollover a full 12 years 
before 
the rest of the UNIX-speaking world. :-)
- TAI is sufficiently different from UNIX time to make implementors 
think 
carefully about their time conversion software.  This is important because 
some UNIX implementations handle leap-seconds and others don't, and this is a 
nice chance to get everything Right the first time.
- TAI-to-UT conversion modules can easily ingest leap-second 
announcements 
without further conversion to a different time base (see, e.g., 
ftp://62.161.69.5/pub/tai/publication/leaptab.txt).  This is important 
because, without proper maintenance of the leap-second table, all of our 
perl6 calendar programs will run an hour late a mere 500 years from now.



Re: Time::Local

2005-07-05 Thread Craig DeForest
Quoth Craig DeForest on Tuesday 05 July 2005 04:59 pm,
 ...This is important
 because, without proper maintenance of the leap-second table, all of our
 perl6 calendar programs will run an hour late a mere 500 years from now.
Uh, sorry -- ...an hour fast a mere 500 years from now.


Re: Time::Local

2005-07-05 Thread Darren Duncan

At 3:36 PM -0700 7/5/05, Dave Whipp wrote:

Darren Duncan wrote:
The object should not store anything other than this single 
numerical value internally (smart caching of conversions aside).


I think we can all either agree with that, or dont-care it. The 
internal implementation is an implementation issue (or library). It 
doesn't need to be defined by the language. The one important thing 
is that that language shouldn't define semantics that require more 
than this single value (e.g. we shouldn't associate the epoch with 
the object).


What I'm saying is that the epoch for a high-precision-knowledge date 
is effectively hard-coded into Perl as a standard and users do not 
specify it or override it at any time.  If this is accepted, then all 
that's left to discuss for these types of dates is what list of 
conversion methods there are and accepted input/output formats. 
Which perhaps is the point.  The main reason implementation would 
have a say is if Perl's built-in functions do not return the 
Date/Time object, but some scalar information instead like Perl 5. 
But I say it should return the object. -- Darren Duncan


Re: Time::Local

2005-07-05 Thread Sam Vilain

Darren Duncan wrote:
Actually, there was a big oversight in my last message.  It does not 
handle approximate or relative dates, such as when you don't know the 
details.


FWIW, this is handled by DateTime::Incomplete, and also will be natively
supported by Date::Gregorian.

You're describing with this and other messages very much how the `Date'
distribution in pugs is being designed.  I'd very much appreciate input
on that interface.

Sam.


Autogenerated attribute accessor names

2005-07-05 Thread Stevan Little
Hello,

As I am building the metamodel, I had a question, I did not find anything 
specifically in 
the docs regarding this.

What should I do when I encounter two attributes which can peacefully co-exist 
as 
attributes, but cause a class when we autogenerate the accessors for them. Here 
is a 
quick example:

class Foo {
has @.bar;
has $.bar;
}

Should $.bar win out because it is defined last? Or would @.bar win because it 
would 
create the accessor first, then when an attempt to create the accessor for 
$.bar is made, 
it will see an entry for bar() already in the class, and so not generate one 
(as that is the 
default behavior when a user-created bar() is made)?

Should we enforce something along the lines of method conflict in roles? So 
that any 
conflicts for autogenerated accessor methods will result in neither of them 
being 
generated and therefore force the user to disambiguate manually?

On some level this might be able to be handled with MMD, and call context 
detection, 
but I think that might actually make things far more confusing than they 
actually need 
to be, but that is just MHO. Especially since it would create difficulties when 
something 
like this is encountered.

class Foo {
has @.bar;
has $.bar;

# the autogenerated mutli method accessors
# multi method bar(Array @value) returns Array;
# multi method bar(Scalar $value) returns Scalar;

method bar () {...}
}

Unless of course we use Yuval's everything is a MMD under the hood idea. But 
that is 
another thread entirely.

Thanks,

Stevan




Re: Time::Local

2005-07-05 Thread Juerd
Dave Rolsky skribis 2005-07-05 15:41 (-0500):
 As for 0 vs 1 as the index, I think this is a bit of a red herring.  If 
 you're constantly using this as an array index you're operating at too low 
 a level (IMO).  If all your programs start with:
  my @DayNames = qw( Sunday Monday Tuesday ... );
 I think you have a bigger problem than simply adjusting for a 1-indexed 
 day number ;)

I think the problem one has is much bigger even if a day *number* is
ever displayed. Then beginning with 1 because that's where most humans
begin counting, is wrong. It's a technical thing, and that should be
kept as simple as possible, and as technical as possible, for easier
compatibility with existing technical things.

Calling Sunday 1 and not having a 0 would certainly upset and offend me.

My weeks begin on Mondays, as do most people's weeks here. At the same
time, I can accept any day as the first day if that first day is 0,
because 0 is technical and internal anyway, not meant for humans.

I'm sure lots of people would want an index 1 to be Sunday, if there is
no index 0. This all is solved simply by NOT skipping 0, and using an
arbitrarily chosen day for the first. Or, well, for compatibility,
Sunday :)

Computers and Perl count from 0. People count from 1. If something
begins at 1, it is expected to be a people's thing. And with week days,
this just doesn't work, as not everyone's week starts at the same day.


Juerd
-- 
http://convolution.nl/maak_juerd_blij.html
http://convolution.nl/make_juerd_happy.html 
http://convolution.nl/gajigu_juerd_n.html


Re: Time::Local

2005-07-05 Thread Sam Vilain

Craig DeForest wrote:

Using the TAI epoch of 1958-01-01 00:00:00 has several advantages:
- TAI is recognized by international standards-setting bodies (BIPM).
	- Perl6 will then shake out the 31-bit time rollover a full 12 years before 


I like this in principle, however I wonder of the merits of professing to
return something of more accuracy than can actually ever be realistically
assured from any of the platforms Perl runs.

For a start, to convert from the available time source - the system clock
- to TAI, you need to know;

  a) current adjustments, or when the lack of adjustments is considered
 valid up to (after that date, of course, if the list of adjustments
 is not updated, getting the time or converting from a time to a date
 on a calendar is an exception).

  b) whether or not the system clock is automatically correcting for
 leap seconds, ie when ntpd is running and sync'ed up.

In any case, I'll add to_TAI as one of the marshalling methods for
Date objects in Date.pm

I guess it comes down to what guarantees we decide to make on the nature
of time().  If a leap second passes while the script is running, can the
value returned by time() regress?

In fact, do we even need a fixed epoch?  Why not just free-wheel it and
make 0 the time the script started, get it to count seconds, and let
interfaces for the system clock / orson database solve the hard problems.

Sam.


Re: Time::Local

2005-07-05 Thread zowie


On Jul 5, 2005, at 6:18 PM, Sam Vilain wrote:


Craig DeForest wrote:


Using the TAI epoch of 1958-01-01 00:00:00 has several advantages:
- TAI is recognized by international standards-setting bodies  
(BIPM).
- Perl6 will then shake out the 31-bit time rollover a full 12  
years before ...


I like this in principle, however I wonder of the merits of  
professing to
return something of more accuracy than can actually ever be  
realistically

assured from any of the platforms Perl runs.



Hmmm Actually, ntpd achieves that sort of accuracy -- but if I  
understand

correctly it anchors the UTC time to the standard, and allows the UNIX
seconds count (which often does not account for new leap seconds, though
some gmtime versions account for old ones) to drift or jump whenever  
a leap
second goes by.  The problem is then that interval calculations that  
include the
leap second are off by one second.  That probably doesn't bother most  
people

but is an endless cause of hassle in scientific applications.

There is also a certain joy that comes from noticing that a tool was  
designed by pedants:
it's great that cal(1) handles the Gregorian reformation correctly  
(or at least, in one
of several arguably correct ways) even though most of us don't deal  
with dates in 1752.


So, er, I guess I'm arguing that time/date stamps, if kept in numeric  
counting-ticks form,
should follow TAI in some easily definable way, which probably means  
keeping track
of leap seconds in a table that can be updated easily.  Even if the  
only interface most
people use is through UTC or civil time via the equivalent of gmtime 
(), IWBNI the
underlying engines knew enough to work well for those people who do  
care about
representing time at such high precision that leap seconds matter.   
If the code is
implemented with enough care to do that right, then the natural epoch  
to use is probably
1958, though as you pointed out the epoch itself is much less  
important than the decision

about what kind of time to track.

Cheers,
Craig





Re: Autogenerated attribute accessor names

2005-07-05 Thread Larry Wall
On Tue, Jul 05, 2005 at 05:26:31PM -0400, Stevan Little wrote:
: What should I do when I encounter two attributes which can peacefully 
co-exist as 
: attributes, but cause a class when we autogenerate the accessors for them. 
Here is a 
: quick example:
: 
: class Foo {
:   has @.bar;
:   has $.bar;
: }

Probably for now we should do the conservative thing and carp as
soon as we notice it, much like for role method conflicts.  We could
relax that later if we find a decent way to disambiguate, but I don't
think there will be great demand for it.  In any event, as with role
conflicts, if they write their own method, it overrides both of them
anyway and they can figure it out them own selves.  If we pretend
attribute declarations are anonymous role declarations, they might
turn out to be just that, especially if we decide it's a useful conceit.

Larry


Re: Time::Local

2005-07-05 Thread Larry Wall
On Tue, Jul 05, 2005 at 06:47:41PM -0600, zowie wrote:

: Hmmm Actually, ntpd achieves that sort of accuracy -- but if
: I understand correctly it anchors the UTC time to the standard,
: and allows the UNIX seconds count (which often does not account for
: new leap seconds, though some gmtime versions account for old ones)
: to drift or jump whenever a leap second goes by.  The problem is
: then that interval calculations that include the leap second are off
: by one second.  That probably doesn't bother most people but is an
: endless cause of hassle in scientific applications.

I think it would be wonderful to anchor our internal time to atomic
time, even if our epoch isn't 1958.  It's more important for our
seconds to stay accurate than our timestamps, and we can make the
approximate interfaces do the right thing if they know they're
supposed to be approximate.  The only problem is that we don't
actually have atomic time available to most of our computers right now.
Eventually we will, and I think it would be wonderful if were ready
for that transition when it happens.  Maybe even to the extent of
pretending to be TAI-based by default even if we're not yet.  We'll
be wrong part of the time regardless of which way we pick.

rant
But I really, really wish UTC hadn't decided to add a leap second
this year.  It really wouldn't have hurt many folks to let midnight
drift a few seconds and then do a major seconds correction at the
end of the century, say.  And it would have solved a lot of other
problems.  Oh well...
/rant

: So, er, I guess I'm arguing that time/date stamps, if kept in numeric
: counting-ticks form, should follow TAI in some easily definable way,
: which probably means keeping track of leap seconds in a table that
: can be updated easily.  Even if the only interface most people use
: is through UTC or civil time via the equivalent of gmtime (), IWBNI
: the underlying engines knew enough to work well for those people
: who do care about representing time at such high precision that leap
: seconds matter.  If the code is implemented with enough care to do
: that right, then the natural epoch to use is probably 1958, though
: as you pointed out the epoch itself is much less important than the
: decision about what kind of time to track.

I agree.  time(2000) - time(1958) should just be a TAI constant.
(Actually, it's a constant in UTC as well--it's just the POSIXly
view of time that must die eventually.  Slewing the clock for
leap seconds is Just Wrong, and someday we'll fix it.  Let's design
with the assumption it will be fixed someday.)

Larry


Re: Autogenerated attribute accessor names

2005-07-05 Thread Stevan Little

Larry,

On Jul 5, 2005, at 9:08 PM, Larry Wall wrote:
If we pretend attribute declarations are anonymous role declarations, 
they might
turn out to be just that, especially if we decide it's a useful 
conceit.


This exact thing occurred to me as I was sitting in traffic on the way 
back from $work. I think it probably makes the most sense to do it this 
way. We can always change it later if it proves to be too restrictive.


Steve



Submethods

2005-07-05 Thread Stevan Little

Again with the metamodel stuff :P

So, I am trying to implement the submethods correctly, and some 
questions occurred to me.


The concept of non-inherited infrastructural methods is fairly simple 
to accomplish in the meta-model, by just giving submethods their own 
dispatch table inside the metaclass. However where I am somewhat 
confused is in how and when they get called.


Take this example for instance:

class Foo {
method bar () { ... }
submethod bar () { ... }
}

Is this an error (Synopsis 12 seems to indicate it is *not* an error)?

When I call bar() on an instance of Foo, which is called? The method? 
or the submethod? Is it somehow dependent upon the calling context? 
(called from within the class, or from outside the class). Take for 
instance, this example:


class Foo {
method bar () { ... }
submethod bar () { ... }

method baz ($self:) {
$self.bar() # which one does this call?
}
}

Or are both called? if so, in what order? On method resolution, should 
I first check the submethod table? or the method table (and on up the 
superclass chain)?


Thanks,

Stevan



Re: Time::Local -- and lexical scope

2005-07-05 Thread Larry Wall
On Tue, Jul 05, 2005 at 03:48:47PM -0700, Dave Whipp wrote:
: Dave Whipp wrote:
: 
: You can use {time - $epoch} or {time.as%d} or {int time}. (That 
: last one is not {+time}, because that would be a floating-point value, 
: not an integer).

Or {time.int}, presumably.

: I was thinking: an epoch is just a time, and int time is a duration -- 
: the number of seconds since the current epoch. So, the following should 
: work:
: 
: for 1 .. 2 - {
:use epoch time();
:sleep 6;
:say int time;
: }
: 
: This should print something close to 6, twice.
: 
: But something niggled me: does the value of the RHS of a use get 
: evaluated at run time, or compile time? In perl5, that could definitely 
: would only execute the Cuse once.

I would not necessarily assume that use is the best interface for
setting what is essentially a lexically scoped variable.

: I could see 3 possible behaviors:
: 
: 1. Cuse sets the epoch for each iteration of the loop, thus calling 
: time() one per iteration

The pragma could arrange to install something in the runtime code
at that point, but it would take extraordinary measures and be
completely unexpected.

: 2. Cuse executes just once, at compile time. Thus seconds iteration 
: prints approximately 12

Or much more than that, given separate compilation.

: 3. Cuse does a compile-time binding of the epoch to the time() 
: function. So each iteration prints 0.

: Which actually happens?

Am I allowed to vote for none of the above?  :-)

Actually what should happen is most like 2, I suspect.

Coming at it from a different angle, I'm thinking we should try to
get rid of built-in none-ary functions like time anyway, and parse them
to expect an argument, on the assumption that this will simplify
MMD.  (In fact, that's a good reason to get rid of the entire
named unary precedence level and treat them all as list operators
for parsing purposes.)  So if we're allowing an optional argument
to time(), then it makes sense to allow time($epoch), where time
can default to a particular epoch, or even to the epoch defined in
the caller's lexical scope.  I'd like time(2000) to be the standard
default, but time(1958) shouldn't be too hard to arrange.

We could set that default pragmatically, but pragmatically speaking,
we should just set the epoch as a lexical variable that is visible
to the default value for the parameter.  Then the caller can
even do something like:

temp $_epoch_ = 1970;

$x = time();# sub time (?$epoch = $CALLER::_epoch_)

I'm not suggesting that's the proper name for the lexical variable.
In fact, we haven't got any convention for forced-lexicals in Perl
6 yet, other than, $_ and $/ are two examples of them, and $?FOO is
a compile-time lexical, and $=FOO is file-scoped in some fashion.
At one point I was thinking $*FOO would let the variable itself
decide if it was lexical or global, on the assumption that $_ is just
short for $*_.  But maybe that's a Bad Idea.  How do we decide which
variables are forced lexicals?  More specifically, how to we request
the compiler to force other variables to be lexical, and poke them
into our lexical pads automatically for us?  I think the epoch is
one of those, however we spell it.  Then different modules can run
with different epochs, as long as all absolute times are passed
as objects.

Larry