Использование исключительных или в объявлениях типа sbcl - PullRequest
0 голосов
/ 22 января 2019

Для такой функции, как:

(defun test (x y)
   (declare (optimize (speed  3)))
   (< x y))

Я вижу предупреждение, содержащее это:

note: 
unable to
  open-code FLOAT to RATIONAL comparison
due to type uncertainty:
  The first argument is a REAL, not a FLOAT.
  The second argument is a REAL, not a RATIONAL.

Если я знаю, что оба аргумента будут RATIONAL xor FLOAT, есть ли подсказка для объявления, которую я могу дать для этого sbcl?

Ответы [ 2 ]

0 голосов
/ 22 января 2019

Вы не можете объявить такого рода отношения между типами, но вы могли бы определить некоторые вспомогательные функции, где тип устанавливается, но не проверяется:

(macrolet ((defexpansion (name type)
             `(progn
                (declaim (inline ,name))
                (defun ,name (x y)
                  (declare (type ,type x y)
                           (optimize (safety 1)
                                     (speed 3)))
                  (< x y)))))
  (defexpansion test-fixnum fixnum)
  (defexpansion test-float float)
  (defexpansion test-rational rational))

Тогда вам нужно толькопроверьте тип первого аргумента, поскольку вы знаете , что второй аргумент обязательно того же типа (именно об этом говорится в объявлении, и вы попросили компилятор доверять вам).

(defun test (x y)
  (etypecase x
    (float (test-float x y))
    (fixnum (test-fixnum x y))
    (rational (test-rational x y))))
0 голосов
/ 22 января 2019

Вы можете предоставить sbcl некоторую информацию о типе ваших данных:

(defun test (x y)
  (declare (optimize (speed  3))
           (type rational x y))
  (< x y))

Вы должны решить, можете ли вы указывать тип x и y при любых обстоятельствах или нет.

Более подробную информацию об объявлении типа вы можете найти в hyperspec и sbcl's manual .

EDIT

Я не знаю, имеет ли это смысл, но можно подумать о другом слое, который решает, какая функция вызывается:

(defun test% (x y)
  (declare (optimize (speed  3)))
  (if (and (typep x 'rational) (typep y 'rational))
      (test-rational x y)
      (test-float x y)))

(defun test-rational (x y)
  (declare (optimize (speed  3))
           (type rational x y))
  (< x y))

(defun test-float (x y)
  (declare (optimize (speed  3))
           (type float x y))
  (< x y))

Я думаю, что есть место для дальнейшей оптимизации с использованием typecase или определенияметоды для каждого типа, использующие CLOS.

...