Skip to main content
added 6 characters in body
Source Link
Drew
  • 79.1k
  • 10
  • 123
  • 257

So the difference between this approach and the use of free variable function in the lexical binding case (that is, the use of a closure that accompaniescouples (a) the lambda form that has free variable function with (b) an environment in which that variable is bound to zerop) is that:

Number 1 means that you cannot use the variable for anything when the lambda form is used as a function, because, hey! - it isn't thereHey! - it isn't there.

So the difference between this approach and the use of free variable function in the lexical binding case (that is, the use of a closure that accompanies the lambda form that has free variable function with an environment in which that variable is bound to zerop) is that:

Number 1 means that you cannot use the variable for anything when the lambda form is used as a function, because, hey! - it isn't there.

So the difference between this approach and the use of free variable function in the lexical binding case (that is, the use of a closure that couples (a) the lambda form that has free variable function with (b) an environment in which that variable is bound to zerop) is that:

Number 1 means that you cannot use the variable for anything when the lambda form is used as a function, because, Hey! - it isn't there.

added 670 characters in body
Source Link
Drew
  • 79.1k
  • 10
  • 123
  • 257

What @Constantine said about lexical and dynamic scoping is true, and it explains the difference from Common Lisp behavior.

However, there is something misleading in your question. This really has nothing to do with macroshas nothing to do with macros. Here is a definition using defun instead of defmacro. Note that you need a quote mark (') before the use of ,function: ',function, because you want 'zerop and not zerop (which would be evaluated as a variable).

(defun complement (function)
  "Return a function that complements the effect of FUNCTION.
The resulting function applies FUNCTION to any number of args
and returns the Boolean complement of the result."
  `(lambda (&rest args)
     (not (apply ',function args))))

(funcall (complement #'zerop) 0)   ; Returns nil
(funcall (complement #'zerop) 3)   ; Returns t

(complement #'zerop) ; Returns (lambda (&rest args) (not (apply (quote zerop) args)))

When you use complement that list is evaluated to a function and used as such.

So the difference between this approach and the use of free variable function in the lexical binding case (that is, the use of a closure that accompanies the lambda form that has free variable function with an environment in which that variable is bound to zerop) is that:

  1. In this approach there is no variable in the resulting form, and

  2. The resulting form is a list, not a function.

Number 1 means that you cannot use the variable for anything when the lambda form is used as a function, because, hey! - it isn't there.

And it means that unless you explicitly go to the trouble of byte-compiling the resulting form (which is a list, whose car is lambda etc.), evaluation is slower, because you are interpreting a list as a lambda form and that as a function - you do not have a (possibly byte-compiled) function directly.

When might you care whether you have a variable at the time the function is used? When you need to do something with that variable as a variable! For example, you assign it another value than function at some point. In most cases you do not need the variable as a variable - it is enough to have its value (in this case, zerop) when the function is used.

What @Constantine said about lexical and dynamic scoping is true.

However, there is something misleading in your question. This really has nothing to do with macros. Here is a definition using defun. Note that you need a quote mark before the use of ,function: ',function, because you want 'zerop and not zerop (which would be evaluated as a variable).

(defun complement (function)
  "Return a function that complements the effect of FUNCTION.
The resulting function applies FUNCTION to any number of args
and returns the Boolean complement of the result."
  `(lambda (&rest args)
     (not (apply ',function args))))

(funcall (complement #'zerop) 0)   ; Returns nil
(funcall (complement #'zerop) 3)   ; Returns t

When you use complement that list is evaluated to a function and used as such.

What @Constantine said about lexical and dynamic scoping is true, and it explains the difference from Common Lisp behavior.

However, there is something misleading in your question. This really has nothing to do with macros. Here is a definition using defun instead of defmacro. Note that you need a quote mark (') before the use of ,function: ',function, because you want 'zerop and not zerop (which would be evaluated as a variable).

(defun complement (function)
  "Return a function that complements the effect of FUNCTION.
The resulting function applies FUNCTION to any number of args
and returns the Boolean complement of the result."
  `(lambda (&rest args)
     (not (apply ',function args))))

(funcall (complement #'zerop) 0)   ; Returns nil
(funcall (complement #'zerop) 3)   ; Returns t

(complement #'zerop) ; Returns (lambda (&rest args) (not (apply (quote zerop) args)))

When you use complement that list is evaluated to a function and used as such.

So the difference between this approach and the use of free variable function in the lexical binding case (that is, the use of a closure that accompanies the lambda form that has free variable function with an environment in which that variable is bound to zerop) is that:

  1. In this approach there is no variable in the resulting form, and

  2. The resulting form is a list, not a function.

Number 1 means that you cannot use the variable for anything when the lambda form is used as a function, because, hey! - it isn't there.

And it means that unless you explicitly go to the trouble of byte-compiling the resulting form (which is a list, whose car is lambda etc.), evaluation is slower, because you are interpreting a list as a lambda form and that as a function - you do not have a (possibly byte-compiled) function directly.

When might you care whether you have a variable at the time the function is used? When you need to do something with that variable as a variable! For example, you assign it another value than function at some point. In most cases you do not need the variable as a variable - it is enough to have its value (in this case, zerop) when the function is used.

added 670 characters in body
Source Link
Drew
  • 79.1k
  • 10
  • 123
  • 257

What @Constantine said about lexical and dynamic scoping is all true.

However, there is something misleading in your question. This really has nothing to do with macros. Here is a definition using defun. Note that you need a quote mark before the use of ,function: ',function, because you want 'zerop and not zerop (which would be evaluated as a variable).

(defun complement (function)
  "Return a function that complements the effect of FUNCTION.
The resulting function applies FUNCTION to any number of args
and returns the Boolean complement of the result."
  `(lambda (&rest args)
     (not (apply ',function args))))

(funcall (complement #'zerop) 0)   ; Returns nil
(funcall (complement #'zerop) 3)   ; Returns t

When you use ',function you are not leaving function as a free variable in the resulting function (lambda form). Instead, because of the backquote surrounding the comma, the value of FUNCTION that is passed to function complement is substituted for ,function, and then quoted.

So when zerop is passed as argument to complement it is substituted for ,function and then quoted, producing 'zerop within the resulting lambda form. The backquote expression constructs a list:

(lambda (&rest args) (not (apply 'zerop args)))

When you use complement that list is evaluated to a function and used as such.

What @Constantine said is all true.

However, there is something misleading in your question. This really has nothing to do with macros. Here is a definition using defun. Note that you need a quote mark before the use of ,function: ',function, because you want 'zerop and not zerop (which would be evaluated as a variable).

(defun complement (function)
  "Return a function that complements the effect of FUNCTION.
The resulting function applies FUNCTION to any number of args
and returns the Boolean complement of the result."
  `(lambda (&rest args)
     (not (apply ',function args))))

(funcall (complement #'zerop) 0)   ; Returns nil
(funcall (complement #'zerop) 3)   ; Returns t

What @Constantine said about lexical and dynamic scoping is true.

However, there is something misleading in your question. This really has nothing to do with macros. Here is a definition using defun. Note that you need a quote mark before the use of ,function: ',function, because you want 'zerop and not zerop (which would be evaluated as a variable).

(defun complement (function)
  "Return a function that complements the effect of FUNCTION.
The resulting function applies FUNCTION to any number of args
and returns the Boolean complement of the result."
  `(lambda (&rest args)
     (not (apply ',function args))))

(funcall (complement #'zerop) 0)   ; Returns nil
(funcall (complement #'zerop) 3)   ; Returns t

When you use ',function you are not leaving function as a free variable in the resulting function (lambda form). Instead, because of the backquote surrounding the comma, the value of FUNCTION that is passed to function complement is substituted for ,function, and then quoted.

So when zerop is passed as argument to complement it is substituted for ,function and then quoted, producing 'zerop within the resulting lambda form. The backquote expression constructs a list:

(lambda (&rest args) (not (apply 'zerop args)))

When you use complement that list is evaluated to a function and used as such.

Source Link
Drew
  • 79.1k
  • 10
  • 123
  • 257
Loading