Function that just returns its argument?
Asked Answered
C

3

9

In Common Lisp, is there a function in the standard library that simply returns the parameter given (i.e. doesn't manipulate the data)? This function would be equivalent to (lambda (x) x). I'm looking to use it as the default for an optional parameter. For example, such a function would replace (lambda (x) x) in:

(defun some-function (value &optional (transformation (lambda (x) x)))
  (other-function (funcall transformation value))
Cara answered 8/7, 2014 at 21:49 Comment(2)
identity is what you are looking forLorrainelorrayne
Couldn't one just quote the parameter given, let it evaluate to itself?Calorie
I
11

Take a look at identity:

Function IDENTITY

Syntax:

identity objectobject

Arguments and Values:

object—an object.

Description:

Returns its argument object.

BTW, the ANSI CL standard specifies almost a thousand symbols. You cannot learn them all overnight. Also, Lisp is a language with a rich history, so if you want something "general purpose", chances are that either the language provides that, or some (semi-)standard library does.

Ask away! Do not reinvent the bike.

Ivar answered 8/7, 2014 at 21:59 Comment(0)
J
10

sds's answer describes the identity function, which meets the specification that you asked for: it's pretty much just (lambda (x) x). However, it is worth noting that in a function like

(defun some-function (value &optional (transformation (lambda (x) x)))
  (other-function (funcall transformation value))

it might be more idiomatic to describe your transformation as a key, and to let nil indicate that no key function should be applied to the value. This behavior is present in many Common Lisp functions. For instance, member takes a key argument that is applied to each element of sequence to produce a value that's compared to the item being searched for:

CL-USER> (member nil '(1 2 3 4 nil 5 6 7 8))
(NIL 5 6 7 8)
CL-USER> (member nil '(1 2 3 4 nil 5 6 7 8) :key 'oddp)
(2 3 4 NIL 5 6 7 8)

The default behavior is the same as if you pass identity as the key:

CL-USER> (member nil '(1 2 3 4 nil 5 6 7 8))
(NIL 5 6 7 8)
CL-USER> (member nil '(1 2 3 4 nil 5 6 7 8) :key 'identity)
(NIL 5 6 7 8)

However, the default value isn't identity, but nil. The HyperSpec for member says about the key:

key—a designator for a function of one argument, or nil.

This is specified in 17.2.1 Satisfying a Two-Argument Test which states that:

If a :key argument is provided, it is a designator for a function of one argument to be called with each Ei as an argument, and yielding an object Zi to be used for comparison. (If there is no :key argument, Zi is Ei.)

If you want to adopt this type of convention, then your code would be something like

(defun some-function (value &optional transformation)
  (other-function (if (null transformation) value (funcall transformation value))))

In your case, this might not be a big difference, but it will avoid an extra function call. In general, this can be helpful because it makes it easier to pass key arguments to library functions without having to worry about whether they're nil or not.

Jolt answered 8/7, 2014 at 22:11 Comment(3)
Since you are talking idiomatic, would slightly better code be a rewrite of the if form along these lines: (defun some-function (value &optional transformation) (other-function (if transformation (funcall transformation value) value))Horseman
@Horseman It well might be. While I very much like working in dynamically typed languages like Common Lisp, I do find that thinking in terms of static typing handy, so usually do (if (null x) …) rather than (if x …), when x isn't something that's conceptually a boolean value. Aside from that, I often like having the simpler of the cases as the consequent, and the more complex as the alternative, so I do prefer something that lets me write (if … value (funcall transformation value)) rather than (if … (funcall transformation value) value). Those are all implementation details…Jolt
@Horseman …though. Since this is a function that others would use, but not see the implementation of, the only idiomatic or non idiomatic part being exposed is whether nil as transformation has the same effect as identity or not. That's the part that other users will see, not the implementation.Jolt
L
2

To expand a bit on the question, #'identity would return its argument when you have a single argument. #'list would return multiple arguments as a list, and #'values would return them as multiple values, they serve the same purpose but have a very different API indeed.

Liquor answered 12/7, 2014 at 15:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.