Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Way to redefine builtin function inside a lisp package

I'm currently writing small implementation of vector arithmetics, and I want to define my own «-» and «+» (and maybe other) functions that will operate on vectors.

And I also want to place all these functions in a package.

And I want this hypothetical package, let's say it's called «vec», to behave like this:

  • While inside the package, I define functions «-» and «+», but when I call + or - (inside the same package), Common Lisp builtins are invoked.
  • If previous is not possible, I want to call builtin + and - as cl:+ and cl:-, but without necessity of explicitly importing every single other needed function from :cl.
  • When I import vec package, or mention it in :use section of definition of another package, common-lisp package's «-» and «+» are still available, and package vec's functions are called like (vec:+ v1 v2), so there is no name conflict between vec:+ and cl:+.

So, what is considered the best (and proper) way to achieve this behaviour?

like image 269
alexey.e.egorov Avatar asked Nov 08 '13 07:11

alexey.e.egorov


1 Answers

It is not possible to define a symbol + and have it refer to + from another package at the same time.

You don't need to import symbols. If they are exported you can use them as foo:+. If they are not exported, they can be used as foo::+.

There is no point of using (in the programmatic sense - sure it makes sense to introduce a package as a namespace for vector operations) a package if you don't want to make symbols accessible in the using package. If you want to write vec:+, then there is no point in using the package VEC. Just export symbols from VEC.

Just for illustration:

CL-USER 6 > (defpackage "VEC"
               (:use "CL")
               (:shadow cl:+ cl:-)
               (:export "+" "-"))
#<The VEC package, 0/16 internal, 2/16 external>

CL-USER 7 > (defun vec:+ (a b) (+ a b))
VEC:+

CL-USER 8 > (defun vec:- (a b) (- a b))
VEC:-

CL-USER 9 > (defpackage "GRAPH" (:use "CL"))
#<The GRAPH package, 0/16 internal, 0/16 external>

CL-USER 10 > (in-package "GRAPH")
#<The GRAPH package, 0/16 internal, 0/16 external>

GRAPH 11 > (defun foo (a b) (+ (vec:+ a b) 42))
FOO

Note, if the current package is VEC, then + refers to VEC:+. For the CL + you would then need to write CL:+.

Always keep in mind:

  • packages are resolved at read time.
  • the current package determines the default package which is used during read time. changing the current package does not change already read symbols.
like image 66
Rainer Joswig Avatar answered Sep 19 '22 01:09

Rainer Joswig