Replacing an ordinary function with a generic function
Asked Answered
S

2

4

I'd like to use names such as elt, nth and mapcar with a new data structure that I am prototyping, but these names designate ordinary functions and so, I think, would need to be redefined as generic functions.

Presumably it's bad form to redefine these names?

Is there a way to tell defgeneric not to generate a program error and to go ahead and replace the function binding?

Is there a good reason for these not being generic functions or is just historic?

What's the considered wisdom and best practice here please?

Slopwork answered 28/6, 2016 at 15:23 Comment(0)
K
7

If you are using SBCL or ABCL, and aren't concerned with ANSI compliance, you could investigate Extensible Sequences:

http://www.sbcl.org/manual/#Extensible-Sequences

http://www.doc.gold.ac.uk/~mas01cr/papers/ilc2007/sequences-20070301.pdf

...you can't redefine functions in the COMMON-LISP package, but you could create a new package and shadow the imports of the functions you want to redefine.

Krakau answered 28/6, 2016 at 16:54 Comment(0)
K
7

Is there a good reason for these not being generic functions or is just historic?

Common Lisp has some layers of language in some of its areas. Higher-level parts of the software might need to be built on lower-level constructs.

One of its goals was being fast enough for a range of applications.

Common Lisp also introduced the idea of sequences, the abstraction over lists and vectors, at a time, when the language didn't have an object-system. CLOS came several years after the initial Common Lisp design.

Take for example something like equality - for numbers.

Lisp has =:

(= a b)

That's the fastest way to compare numbers. = is also defined only for numbers.

Then there are eql, equal and equalp. Those work for numbers, but also for some other data types.

Now, if you need more speed, you can declare the types and tell the compiler to generate faster code:

(locally
  (declare (fixnum a b)
           (optimize (speed 3) (safety 0)))
  (= a b))

So, why is = not a CLOS generic function?

a) it was introduced when CLOS did not exist

but equally important:

b) in Common Lisp it wasn't known (and it still isn't) how to make a CLOS generic function = as fast as a non-generic function for typical usage scenarios - while preserving dynamic typing and extensibility

CLOS generic function simply have a speed penalty. The runtime dispatch costs.

CLOS is best used for higher level code, which then really benefits from features like extensibility, multi-dispatch, inheritance/combinations. Generic functions should be used for defined generic behavior - not as collections of similar methods.

With better implementation technology, implementation-specific language enhancements, etc. it might be possible to increase the range of code which can be written in a performant way using CLOS. This has been tried with programming languages like Dylan and Julia.

Presumably it's bad form to redefine these names?

Common Lisp implementations don't let you replace them just so. Be aware, that your replacement functions should be implemented in a way which works consistently with the old functions. Also, old versions could be inlined in some way and not be replaceable everywhere.

Is there a way to tell defgeneric not to generate a program error and to go ahead and replace the function binding?

You would need to make sure that the replacement is working while replacing it. The code replacing functions, might use those function you are replacing.

Still, implementations allow you to replace CL functions - but this is implementation specific. For example LispWorks provides the variables lispworks:*packages-for-warn-on-redefinition* and lispworks:*handle-warn-on-redefinition*. One can bind them or change them globally.

What's the considered wisdom and best practice here please?

There are two approaches:

  • use implementation specific ways to replace standard Common Lisp functions

This can be dangerous. Plus you need to support it for all implementations of CL you want to use...

  • use a language package, where you define your new language. Here this would be standard Common Lisp plus your extensions/changes. Export everything the user would use. In your software use this package instead of CL.
Kordofanian answered 28/6, 2016 at 23:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.