December 2019

In Lisp you can pass an operator as a parameter. Instead of (+ a b) it's possible to run:

(= opdo (fn (op a b) (op a b)))
(opdo + a b)

Is this a good thing?

I used to think so. At a first glance, it gives the user more flexibility and is semantically sound, even if unnecessary. The function takes the operator as input instead of hardcode it. Functions accept other functions as parameters, so why not also accept operators as parameters?

What made me unsure if passing operators as parameters is a good thing was adding live code walking in Lisp. When + is passed as a parameter, the live code walker no longer detects + as the operator that gets called with parameters. It detects a function call. (op a b) is a function call. It then looks for a code walker for functions, sees that there isn't one, and doesn't attempt to rewrite the source code. When + is passed as a parameter it sneaks by the live code walker. The user can add more logic of course in the live code walker to check if the first parameter to a function call evaluates to the + sign but it's more work. Is doing more work when writing code walkers a good thing? I don't think so.

Same with adding safe mode in Lisp. If sysdo is passed as a parameter to a function and called from there, the acl access check won't match it since the function call isn't named sysdo, and sysdo can execute unsafe code. The user can get hacked.

It takes more effort by a highly dynamic Lisp to make live code walking and safe mode work with operators passed as parameters. I hope the tradeoff is only decreased performance. In addition to the existing code for function calls that detects live code walking and verifies the acl under safe mode, more code must be added for function calls that identifies their first parameter at runtime, evaluates it, and if the parameter is a built-in operator, looks it up in the code-walkers and the acl for a match.