Many applications deal with events that have occurred at different points in time. Often, these times are relatively recent, such as a list of emails in an inbox or a list of status updates on a social network. When we talk about when an event occurred, it is sometimes useful to be precise (e.g., Thu May 13 19:12:02 2010), and other times it is better to be a bit softer (e.g., about a minute ago).
This function gets built from time-to-time in various languages: for example in Python and Javascript. I thought it might be fun to see how simple it could be in Factor.
A very useful type of conditional combinator is called cond
. It applies to a sequence of quotations. The first elements in the sequence are pairs of quotations. The combinator proceeds to call the first quotation in each pair until a true value is yielded, at which point it calls the second quotation in that pair and stops iterating. A final quotation can be provided to handle the case where none of the pairs returned a true value.
In typical applicative languages, this would be provided by an "if/else if/else" chain. It is a general pattern and is used in Factor to implement case
(a type of switch statement).
Using a few vocabularies:
USING: combinators formatting kernel math ;
We will write a word that takes the number of seconds that something happened in the past, and calculates how long ago it was in "human terms":
: relative-time ( seconds -- string ) dup 0 < [ "negative seconds" throw ] when { { [ dup 1 < ] [ drop "just now" ] } { [ dup 60 < ] [ drop "less than a minute ago" ] } { [ dup 120 < ] [ drop "about a minute ago" ] } { [ dup 2700 < ] [ 60 / "%d minutes ago" sprintf ] } { [ dup 5400 < ] [ drop "about an hour ago" ] } { [ dup 86400 < ] [ 3600 / "%d hours ago" sprintf ] } { [ dup 172800 < ] [ drop "1 day ago" ] } [ 86400 / "%d days ago" sprintf ] } cond ;
Fairly concise as it turns out. If it wasn't for the minor stack manipulation, you might say this was getting very close to the essence of the algorithm.
No comments:
Post a Comment