Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

override/overload the + operator to operate on common lisp vectors

I wish to overload the + operator to work on common lisp vectors -- just as it would for vectors in linear algebra. Is it possible to overload with the + operator?

Here is my intended definition:

 (defmethod + ((v1 vector) (v2 vector))

Thanks in advance for all the help!

like image 551
CodeKingPlusPlus Avatar asked Dec 03 '22 19:12

CodeKingPlusPlus


2 Answers

If I were to do this, I would start by doing it in a separate package. I would then write a general function that uses binary operators:

(defun + (&rest addends)
  (reduce #'binary+ (cdr addends) :initial-value (car addends)))

(defgeneric binary+ (addend1 addend2))

Then you can define methods on the generic function binary+ that would allow you to add two vectors, a vector and a scalar, ...

Something that would be a suitable wrapper-generating macro:

(defmacro define-operator (op &key (binary-signifier :binary) (package *package*)
  "Defines a generic operator OP, being essentially a reduce operation using
   a generic function whose name is a concatenation of BINARY-SIGNIFIER and OP."
  (let ((op op)
        (binary (intern (concatenate 'string
                                          (string  binary-signifier)
                                          (string op))
                        package)))
    `(progn
       (defun ,op (&rest args)
          (reduce (function ,binary) (cdr args) :initial-value (car args)))
       (defgeneric ,binary (arg1 arg2)))))

Then you can define methods, as per Joshua Taylor's answer:

(defmethod binary+ ((x number) (y number))
  (cl:+ x y))

(defmethod binary+ ((x vector) (y vector))
  (map 'vector 'cl:+ x y))

(defmethod binary+ ((x list) (y list))
  (map 'list 'cl:+ x y))
like image 78
Vatine Avatar answered Dec 05 '22 08:12

Vatine


This is an extension of Vatine's answer, but with some more detail to make the implementaiton clearer:

(defpackage #:generic-arithmetic 
  (:use "COMMON-LISP")
  (:shadow "+"))

(in-package #:generic-arithmetic)

(defun + (&rest addends)
  (reduce 'binary+ (cdr addends) :initial-value (car addends)))

(defgeneric binary+ (addend1 addend2))

(defmethod binary+ ((x number) (y number))
  (cl:+ x y))

(defmethod binary+ ((x vector) (y vector))
  (map 'vector 'cl:+ x y))

(defmethod binary+ ((x list) (y list))
  (map 'list 'cl:+ x y))

(+ 1 1)
;=> 2

(+ #(1 2) #(0 -1))
;=> #(1 1)

(+ '(1 3) '(3 1))
;=> (4 4)
like image 26
2 revs Avatar answered Dec 05 '22 09:12

2 revs