
This program has a surprising-to-me error: #lang racket
(define-syntax (m stx)
(syntax-case stx ()
[(_ e1 )
(local-expand #'e1 'module null)]))
(m (define x 1))
It says: define-values: not allowed in an expression position
. But where is the expression position?

@samth You can’t expand define-values
, enclosing contexts always partial expand and discover define-values
, then handle the definition themselves (so define-values
never handles itself). But I imagine you already knew that, so is the point you’re making just that the error message is confusing?

it’s very confusing

It could be changed to say something along the lines of “cannot be expanded directly, only partially expanded”, but ultimately the confusion of how definitions in general work seems hard to avoid (since the notion of partial expansion is a little non-obvious).

I think the underlying source of confusion is that m
looks like it ought to be an identity macro of some sort, but (m (define ...))
doesn’t work in places where (define ...)
works

If m
just expanded to e1
, it would work fine, so I’m not sure what you mean by that.

What I mean is, I think of local-expand
as something that changes when expansion occurs, but not something that changes the result of expansion. So if the only thing a macro does is local-expand
, with nothing else going on whatsoever, I would intuit that it’s not doing anything at all and should act like an identity function.

That is what I meant by “the notion of partial expansion is a little non-obvious”.

Yes. I gather that this intuition does not work here. I’m saying that it’s a shame it doesn’t, and that the fact that it doesn’t is confusing.

anyone know how to find the numbers of seconds in a day using gregor
? I’ve been looking for a function f
where (f (days 1))
gives the right number

@ben I think you can’t, in general

No way. I’m not looking for the number of seconds in April 15th 2019. I just to know “how many seconds in 24 hours”?

but one day is not always equal to 24 hours

Can period-between be used?

wait, nevermind I’m confused now: > Gregor assumes that all days have exactly 86,400 seconds. Therefore, it is based fundamentally on mean solar time, or Univeral Time, and not on Coordinated Universal Time (UTC), the civil time scale adopted by most of the world. In the interest of reconciling the SI second to a close approximation of mean solar time, UTC occasionally inserts an extra leap second into a day.

wait, why are you confused now - you found the answer.

no! 86400 is not the answer I want

I’m confused because I remember opening a github issue asking about this and getting a different answer of some sort

@ben I know, so the answer is “no” :wink:

but that’s funny about the docs — I was thinking @notjack was right and I should use a constant instead of going through gregor

I don’t think period-between works


I don’t understand why 86,400 is not the answer you want

leap seconds!

But if ben is explicitly not looking for the number of seconds on a particular day, then how are leap seconds relevant?

good point!

Oh wait, now I know why this is relevant: daylight savings time

Even then, that would involve a specific day

Unless @ben is just saying he doesn’t want to write the magic number “86,400” in his code

In that case, I think @soegaard2 is right, and period-between
can get you there

my assumption is that a function f
from date-period?
to a number of seconds shouldn’t break the invariant that adding the original date period to a moment gives the same answer as adding (seconds (f p))
does

but period-between
expects datetimes, not periods

Yes, you have to indirect through a date, since although days are always 86,400 seconds long, the same does not hold for other time units

So you couldn’t have an operation that, say, converts (months 1)
into seconds without knowing a specific month (since months vary in length)

But if you’re relying on the assumption that all days have the same length, anyway (which you are, since you’re using a constant instead of recalculating it as-needed), then you can just make two datetimes exactly one day apart and use period-between
on that.

ok thanks everyone

@ben Number of seconds in a local day, then?

You should be able to get that. Lemme take a look.

(Sorry, mentioned the wrong Ben initially.)

number of seconds in (hours 24)
would be ok too

But, to be clear: - Gregor does not do proper UTC, so leap seconds won’t be counted. - A local date can have a number of seconds different from 86,400.

That would always have to be 86,400. (Wow, I keep tagging the wrong Ben. I Slack poorly.)

I think time-periods should be able to get you that info. But sometimes I forget what functionality is in gregor and what is in an unreleased successor to gregor. I’ll check on all of this.

Huh. Looks like that function does not exist in gregor. I was looking for a time-period->seconds
, which is a perfectly sensible function (unlike date-period->seconds
which would be nonsense, unless you anchored the period to a particular date in a particular zone).

Yeah, datetime-lib
(again, unreleased) has a time-period->nanoseconds
. I don’t see any reason not to add that to gregor
, too.

Right now, I think the only way to get this is: > (require gregor/period)
> (period-between (datetime 2000 1 1) (datetime 2000 1 2) '(seconds))
#<period of 86400 seconds>

which others have mentioned

(And which is clearly not convenient.)

@jaz why would date-period->seconds
be unreasonable, exactly? Since date periods seem unrelated to any fixed point in time and leap seconds are ignored

Because I wouldn’t want these two things to produce different results: - (+date-period date-provider date-period)
- (+ seconds date-provider (date-period->seconds date-period))

What it comes down to is that a date-period
does not represent something that can be reduced to a number of seconds, unless you anchor it.

How many seconds are there in a month?

@jaz Are there ever points in time where (+time-period d (hours n))
is not equal to (+time-period d (seconds (* 60 n)))
? Like, due to daylight savings time or something?

Nope

All time periods are reducible to nanoseconds, because of the “we do not care about leap seconds” rule.

I think I’m just confused about what date periods are exactly. They don’t seem to be anchored to any points in time, but they also don’t represent a fixed amount of time because adding (days 1)
is not always the same as adding (hours 24)

Daylight savings time doesn’t change the number of seconds in a minute or hour, or anything like that.

@notjack That’s right. They represent abstract quantities which can be added to concrete date-providers.

They are also the result of a period-between
, which starts with two concrete items. But this is admittedly more problematic. And gregor
in fact handles this poorly. Witness: > (period-between (date 2000 1 1) (date 2000 1 2) '(seconds))
#<period [empty]>

The correct response is to reject the question, not to give a baffling answer.

Ok, that answer doesn’t make sense.

This is so weird to me because it’s not like other cases I think of as similar, like converting between yards and inches, where there’s two different abstract units for the same conceptual dimension. Here’s there’s two distinct dimensions of time, where one is seconds and the other is these weird calendar days. They’re not measuring the same thing at all.

That’s exactly right.

What if we just…. never used date periods?

There’s no requirement to

But I’m not going to get rid of date arithmetic, because that’s genuinely useful.

Even though it’s weird.

yeah for things like recurring schedules it does make sense

I don’t want “do this every seven days, starting at midnight on this day” to oscillate back and forth between actually doing it at midnight and doing it at 1AM / 11PM based on how daylight savings time works out

I should mention that the above example from gregor
isn’t problematic in datetime-lib
, because there are separate date-period-between
, time-period-between
, and period-between
functions, which have contracts limiting their use.

I think a period like (period [days 11] [seconds 42])
is weird because it’s implying that these units are compatible somehow

Yeah, and we could just completely separate date and time periods. That might be better.

Calling them date periods and time periods but not unifying them is also kind of confusing, because it makes you wonder why there aren’t generic period operations. Maybe if they were just called completely separate things?

Makes sense

What do datetime libraries in other languages usually call these things? I think time-period
is roughly equivalent to java.time.Duration

Yeah, java.time
has separate notions of Period and Duration, which roughly correspond to date and time periods in gregor.

hmmm, and they do have a common TemporalAmount
interface and they specify that Duration
assumes fixed 24-hour days while Period
doesn’t (because it doesn’t represent fractions of days at all)