From: K. Ari Krupnikov
Subject: (month year) from universal-time
Date: 
Message-ID: <86br3rdct9.fsf@deb.lib.aero>
I'm still getting used to multiple return values. What's the easiest
way to make a list that contains month and year from a universal-time?

I can do this, but it seems horribly verbose for what it does:

(multiple-value-bind
      (second minute hour date month year day daylight-p zone)
    (decode-universal-time timestamp)
  (list month year))

Ari.

-- 
Elections only count as free and trials as fair if you can lose money
betting on the outcome.

From: Nathan Baum
Subject: Re: (month year) from universal-time
Date: 
Message-ID: <de97v5$4ov$1@newsg1.svr.pol.co.uk>
K. Ari Krupnikov wrote:
> I'm still getting used to multiple return values. What's the easiest
> way to make a list that contains month and year from a universal-time?
> 
> I can do this, but it seems horribly verbose for what it does:
> 
> (multiple-value-bind
>       (second minute hour date month year day daylight-p zone)
>     (decode-universal-time timestamp)
>   (list month year))
> 
> Ari.
> 

Hmm. I got:

(defun nths (indices list)
   (loop for i in indices
         collecting (nth i list)))

(nths '(4 5) (multiple-value-list (decode-universal-time timestamp)))

Perhaps it might be worth making a function like

   (get-time-fields (:month :year) (decode-universal-time timestamp))

If you'll be splitting apart times a lot.
From: Damien Diederen
Subject: Re: (month year) from universal-time
Date: 
Message-ID: <87r7cnxx6d.fsf@keem.bcc>
Hi,

Nathan Baum <···········@btinternet.com> writes:
> K. Ari Krupnikov wrote:
>> I'm still getting used to multiple return values. What's the easiest
>> way to make a list that contains month and year from a universal-time?
>> I can do this, but it seems horribly verbose for what it does:
>> (multiple-value-bind
>>       (second minute hour date month year day daylight-p zone)
>>     (decode-universal-time timestamp)
>>   (list month year))
>> Ari.
>
> Hmm. I got:
>
> (defun nths (indices list)
>   (loop for i in indices
>         collecting (nth i list)))
>
> (nths '(4 5) (multiple-value-list (decode-universal-time timestamp)))

While that solution has the advantage to work at runtime, macrology
helps even more if one does not need that flexibility.  For example,

  (binding-some-values ((4 month) (5 year))
      (decode-universal-time timestamp)
    (list month year))

can be transformed using ('cond-let' is described below):

  (defmacro binding-some-values (some-bindings form &body body)
    (labels ((collect-bindings (index bindings ignored)
               (cond-let (_ (minusp index)
                            (values bindings ignored))
                         (entry (assoc index some-bindings)
                                (collect-bindings (1- index)
                                                  (cons (second entry) bindings)
                                                  ignored))
                         (_ t
                            (let ((symbol (gensym "IGNORED-VALUE-")))
                              (collect-bindings (1- index)
                                                (cons symbol bindings)
                                                (cons symbol ignored)))))))
      (multiple-value-bind (bindings ignored)
          (collect-bindings (reduce #'max some-bindings :key #'car) nil nil)
        `(multiple-value-bind ,bindings
             ,form
           (declare (ignore ,@ignored))
           ,@body))))

Maybe using positional parameters is more intuitive:

  (multiple-value-bind*
        (_ _ _ _ month year)
      (decode-universal-time 0)
    (list month year))

Such a form is transformable by:

  (defmacro multiple-value-bind* (maybe-vars form &body body)
    (let ((pairs (mapcar (lambda (symbol)
                           (if (eq symbol '_)
                               (let ((ignored (gensym "IGNORED-VALUE-")))
                                 (cons ignored ignored))
                               (cons symbol nil))) maybe-vars)))
      `(multiple-value-bind
             ,(mapcar #'car pairs)
           ,form
         (declare (ignore ,@(remove nil (mapcar #'cdr pairs))))
         ,@body)))

Here is the 'cond-let' utility used in 'binding-some-values':
 
  (defmacro cond-let (&rest clauses)
    "Syntax: COND-LET {no-binding-clause | binding-clause}* => result*
  
  no-binding-clause ::= (_ test-form form*)
  binding-clause ::= (var test-form form*)
  
  COND-LET is similar to COND, but allows binding the result of the
  test forms.  The expansion of 'clause' depends on its first
  element:
  
   * _: No binding is established, 'test-form' and 'form*' are used
     exactly like in COND;
  
   * Other symbol: a new binding is established between that symbol
     and the result of evaluating 'test-form'; the 'form*' forms
     are executed using that binding when its value is not NIL."
    (when clauses
      (destructuring-bind (clause . other-clauses) clauses
        (destructuring-bind (binding test-form &body body) clause
          (flet ((gen-1 (test)
                   `(if ,test (progn ,@body) (cond-let ,@other-clauses))))
            (case binding
              (_
               (gen-1 test-form))
              (otherwise
               `(let ((,binding ,test-form))
                  ,(gen-1 binding)))))))))

Cu,
Damien.

-- 
http://foobox.net/~dash/

I can resist everything except temptation.
                --Oscar Wilde
From: Jeff Cunningham
Subject: Re: (month year) from universal-time
Date: 
Message-ID: <pan.2005.08.22.03.07.15.451991@cunningham.net>
> I can do this, but it seems horribly verbose for what it does:
> 
> (multiple-value-bind
>       (second minute hour date month year day daylight-p zone)
>     (decode-universal-time timestamp)
>   (list month year))

This is slightly less verbose:

(multiple-value-bind (s m h d mn yr) 
      (decode-universal-time timestamp)
  (declare (ignorable (s m h d)))
  (list (mn yr)))

You don't need to bind to any variables beyond the last one you're
interested in.

-jeff cunningham      
From: K. Ari Krupnikov
Subject: Re: (month year) from universal-time
Date: 
Message-ID: <86pss6bjep.fsf@deb.lib.aero>
Jeff Cunningham <·······@cunningham.net> writes:

> You don't need to bind to any variables beyond the last one you're
> interested in.

Ah! Thank you. I missed that fact.

Still verbose, but a little shorter.

Ari.

-- 
Elections only count as free and trials as fair if you can lose money
betting on the outcome.