LINUX.ORG.RU

История изменений

Исправление Jini, (текущая версия) :

На с++

До кучи два моих варианта. В C++ используется перегрузка operator<, вот также на лиспе:

(defstruct person
  (name          "" :type string)
  (department-id 0  :type fixnum))

(defgeneric less (a b))

(defmethod less ((a real) (b real))
  (< a b))

(defmethod less ((a string) (b string))
  (string< a b))

(defmethod less ((a sequence) (b sequence))
  (eq (some (lambda (x y)
              (cond
                ((less x y) t)
                ((less y x) '#:false)))
            a b)
      t))

(defun make-test-persons ()
  (loop
    :repeat 10
    :collect (make-person :name (format nil "name~d" (random 10))
                          :department-id (random 3))))

(defun test-3.1 ()
  (sort (make-test-persons) #'less
        :key (lambda (person)
               (list (person-department-id person)
                     (person-name          person)))))

(defun test-3.2 ()
  (sort (make-test-persons) #'string< :key #'person-name))

В отличие от C++, перегрузка идёт в рантайме. Также есть оверхед в создании списков при каждом вызове оператора сравнения структур. От этого можно избавиться макросами, как обычно:

(defmacro multiple-less ((a b) &body clauses)
  (let ((original-a (gensym "A"))
        (original-b (gensym "B")))
    (labels ((less (clauses)
               (destructuring-bind (form &optional (key #'identity)) (pop clauses)
                 `(let ((,a (funcall ,key ,original-a))
                        (,b (funcall ,key ,original-b)))
                    ,(if clauses
                       `(cond
                          (,form
                            t)
                          ((let ((,a ,b) (,b ,a))
                             ,form)
                           nil)
                          (t
                            ,(less clauses)))
                       form)))))
      (if clauses
        `(lambda (,original-a ,original-b)
           ,(less clauses))
        (constantly t)))))
                   
(defun test-3.1* ()
  (sort (make-test-persons)
        (multiple-less (a b)
          ((< a b)       #'person-department-id)
          ((string< a b) #'person-name))))

Я думаю, что если поколдовать с декларациями, этот код будет эквивалентен C++ в плане скорости.

Исходная версия Jini, :

На с++

До куч два моих варианта. В C++ используется перегрузка operator<, вот также на лиспе:

(defstruct person
  (name          "" :type string)
  (department-id 0  :type fixnum))

(defgeneric less (a b))

(defmethod less ((a real) (b real))
  (< a b))

(defmethod less ((a string) (b string))
  (string< a b))

(defmethod less ((a sequence) (b sequence))
  (eq (some (lambda (x y)
              (cond
                ((less x y) t)
                ((less y x) '#:false)))
            a b)
      t))

(defun make-test-persons ()
  (loop
    :repeat 10
    :collect (make-person :name (format nil "name~d" (random 10))
                          :department-id (random 3))))

(defun test-3.1 ()
  (sort (make-test-persons) #'less
        :key (lambda (person)
               (list (person-department-id person)
                     (person-name          person)))))

(defun test-3.2 ()
  (sort (make-test-persons) #'string< :key #'person-name))

В отличие от C++, перегрузка идёт в рантайме. Также есть оверхед в создании списков при каждом вызове оператора сравнения структур. От этого можно избавиться макросами, как обычно:

(defmacro multiple-less ((a b) &body clauses)
  (let ((original-a (gensym "A"))
        (original-b (gensym "B")))
    (labels ((less (clauses)
               (destructuring-bind (form &optional (key #'identity)) (pop clauses)
                 `(let ((,a (funcall ,key ,original-a))
                        (,b (funcall ,key ,original-b)))
                    ,(if clauses
                       `(cond
                          (,form
                            t)
                          ((let ((,a ,b) (,b ,a))
                             ,form)
                           nil)
                          (t
                            ,(less clauses)))
                       form)))))
      (if clauses
        `(lambda (,original-a ,original-b)
           ,(less clauses))
        (constantly t)))))
                   
(defun test-3.1* ()
  (sort (make-test-persons)
        (multiple-less (a b)
          ((< a b)       #'person-department-id)
          ((string< a b) #'person-name))))

Я думаю, что если поколдовать с декларациями, этот код будет эквивалентен C++ в плане скорости.