Why do some lisps put the function name outside of the argument list in a function definition?
Asked Answered
H

3

8

common lisp and clojure do

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

racket/scheme does

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

The latter makes more sense to me because the syntax for function definition and invocation is similar. What's the reasoning for the former?

Hypotension answered 21/1, 2017 at 0:19 Comment(1)
I think the real answer is 'history': Scheme & its variants made one choice, MACLISP and its descendants made another. I’m fairly sure that other early Lisps which don't have living descendents had yet other syntaxes: I forget what InterLisp did, but it was probably something weird and different.Suspensor
S
13

TL;DR It's not quite as simple as you put it. The syntax is slightly more different and every time someone create a language they get to decide 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 Scheme (and the descendant Racket) you have one namespace for both variables and functions. Thus you use define for everything.

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

Now define has a short cut for that last one, which is:

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

So the rule is if the first part is a pair? it is supposed to be expanded to the longer form with lambda. That it resembles an application is just a conicident I guess. This extra feature is just to save some keystrokes and is often omitted in books like The little Schemer since its confusing to have two ways and the learner and they might think defining a binding for a function is more special than defining 10, which is ridiculous. The rest argument usually confuses. eg. these are the same:

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

In Common Lisp you have two namespaces and thus defun is only used for global scope and there are function equivalents of variable forms that makes functions. in defun you have a list first argument in Common Lisp too, but it does something completely different:

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

This provides a way to get the same symmetry as other accessors in CL. eg. if (car x) gets the car value from a cons (setf (car x) 10) will alter it. In my example name can be used in the same manner as car. It's quite handy.

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

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

defn is just a shorthand version just like the define that starts with a pair. How it didn't end up more similar to Scheme is perhaps either the fact that the parameter data is an array or that they kept syntax as close to the original as possible. If I remember correctly you can have a function name as second argument with fn as well making fn and defn look almost identical.

Subtotal answered 21/1, 2017 at 1:27 Comment(0)
Z
12

The latter makes more sense to me because the syntax for function definition and invocation is similar.

In Common Lisp the function definition generally is not similar to the invocation, thus it makes no sense to pretend they do.

This is a valid function defintion:

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

These are valid calls for 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 from the definition argument list.

In the case of DEFMETHOD a definition may look like:

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

and a call would be

(setf (foobar object) 10)

Summary

In Common Lisp function definitions won't look like calls anyway

Excursion

It's simple to define a Scheme-like syntax for simple CL functions:

(defmacro define ((name &rest args) &body body)
  `(defun ,name ,args ,@body))

CL-USER 36 > (macroexpand-1 `(define (foo a b c) (baz) (bar)))
(DEFUN FOO (A B C) (BAZ) (BAR))
T

Some programs even use something similar...

Zymo answered 21/1, 2017 at 2:20 Comment(0)
N
0

Function definition is just an operation in the Lisp family. There is actually little meaning in making function definition similar to function application.

Nisen answered 21/1, 2017 at 0:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.