Why do some lisps put a function name outside the argument list in a function definition?

generic lisp and clojure do

(defn function-name (arg1 arg2) (body)) 

racket / circuit

 (defn (function-name arg1 arg2) (body)) 

The latter makes more sense to me, because the syntax for defining a function and calling is similar. What are the arguments for the first?

+6
source share
3 answers

The latter makes more sense to me, because the syntax for defining a function and calling is similar.

In Common Lisp, defining a function is usually not like a call, so it makes no sense to pretend what they do.

This is a valid defintion function:

 (defun foo (arg1 arg2 &optional (ovar 10) &rest args &key (ak 11 ap) &allow-other-keys &aux (aux1 12)) (list arg1 arg2 ovar args ak ap aux1)) 

These are valid calls for the above:

 (foo 1 2) (foo 1 2 3) (foo 1 2 3 :ak 4) (foo 1 2 3 :foo 10 :ak 4) 

Thus, the call arguments look different than the list of definition arguments.

In the case of DEFMETHOD definition might look like this:

 (defmethod (setf foobar) :around ((value integer) (object foo)) (setf (slot-value object 'a) value)) 

and the challenge will be

 (setf (foobar object) 10) 

Summary

In Common Lisp, function definitions will not look like calls anyway

Sightseeing

A simple Scheme syntax definition for simple CL functions:

 (defmacro define ((name &rest args) &body body) `(defun ,name ,args ,@body)) CL-USER 36 > (macroexpand-1 `(define (foo abc) (baz) (bar))) (DEFUN FOO (ABC) (BAZ) (BAR)) T 

Some programs even use something similar ...

+11
source

TL DR It's not as easy as you put it. The syntax is slightly different, and each time someone creates the language they get to solve the new syntax, usually to make it more concise, that previous languages ​​or the language has a design that requires it. Of course, what is β€œbetter” is a matter of opinion.

In the schema (and the Racket stream), you have one namespace for both variables and functions. This way you use define for everyone.

 (define variable 10) (define function (lambda (arg1 arg2) body ...)) 

Now define has a short length for the last:

 (define (function arg1 arg2) body ...) 

So, is it a rule if the first part is pair? , it should be expanded to a longer form using lambda . That this looks like an application is just a conical incident, which I assume. This extra function is just to save some keystrokes and is often skipped in books like The Little Scheme, because it gets confused by having two paths and a student, and they might think that defining a binding for a function is more important than defining 10 which is funny. The rest of the argument is usually confusing. eg. they are the same:

 (define (test . x) x) (define test (lambda xx)) 

In Common Lisp, you have two namespaces, and therefore defun used only for the global scope, and there are equivalents of variable form functions that create functions. in defun , you have the first argument to the list in Common Lisp, but it does something completely different:

 (defun (setf name) (new-value) body ...) 

This makes it possible to obtain the same symmetry as other accessors in the CL. eg. if (car x) gets the value of the car from cons (setf (car x) 10) , this will change it. In my example, name can be used in the same way as car . It is very comfortable.

Clojure does this with def and fn and uses an array for parameters:

 (def function (fn [arg1 agr2] body ...)) 

defn is just a shortened version, like define , which starts with a pair. As it does not end up more similar to Scheme, perhaps it is the fact that the parameter data is an array or that they retain the syntax as close to the original as possible. If I remember correctly, you can have the function name as the second argument with fn , and make fn and defn look almost the same.

+13
source

A function definition is just an operation in the Lisp family. In fact, there is little point in defining a function similar to a functional application.

+1
source

Source: https://habr.com/ru/post/1014273/


All Articles