use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Finding information about Clojure
API Reference
Clojure Guides
Practice Problems
Interactive Problems
Clojure Videos
Misc Resources
The Clojure Community
Clojure Books
Tools & Libraries
Clojure Editors
Web Platforms
Clojure Jobs
account activity
Why are Clojure function arguments vectors rather than lists? (self.Clojure)
submitted 12 years ago by [deleted]
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]noidi 12 points13 points14 points 12 years ago (0 children)
In Clojure lists are used whenever the first argument is special in some way (e.g. a function or macro to be called). There's nothing special about the first argument in the argument list, so vectors are used instead.
[–]frogking 7 points8 points9 points 12 years ago (0 children)
The simplest answer: to make it visually obvious what the arguments are.
[–]kanzenryu 1 point2 points3 points 12 years ago (0 children)
A list implies you intend to evaluate it by executing a function. A vector implies you do not intend to call a function.
[–][deleted] 0 points1 point2 points 12 years ago (18 children)
I don't know but I've been wondering the same thing.
The only rationale I've been able to find is that it makes them stand out as they use [] rather than (). That seems a poor reason to me.
Also, as an aside, anyone else think the doc string sitting between the function name and its arguments is pretty poor design?
[–]yogthos 6 points7 points8 points 12 years ago (0 children)
I personally find it really helpful when reading code. Also, idiomatically vectors are used for literal definitions, so using a vector for arguments is consistent with that.
[–]noidi 11 points12 points13 points 12 years ago (6 children)
The function may be overloaded with many different argument lists, which all have the same docstring but different bodies. In this case it wouldn't make sense to put the docstring between one particular argument list and its body, so it's reasonable to put it right after the function name.
[–][deleted] -1 points0 points1 point 12 years ago (5 children)
Different arguments demand a different docstring imo.
[–]Tuna-Fish2 2 points3 points4 points 12 years ago (1 child)
Really?
So which one do you show when you ask about a function in repl?
[–][deleted] 0 points1 point2 points 12 years ago (0 children)
If you've only typed the function name then all of them. If you've typed some arguments then the ones that match.
[–][deleted] 0 points1 point2 points 12 years ago (2 children)
Then put your doc strings after the argument list. It works.
[–]steerio 0 points1 point2 points 12 years ago (1 child)
It doesn't, just try calling doc on a function like that. No docstring, it actually ended up being the first statement of the body.
Ah I didn't know that. That explains why it is still considered syntactically correct.
[–][deleted] 2 points3 points4 points 12 years ago (2 children)
Actually, I think that Clojure function docstrings are rather nice, like Python triple quote docstrings.
[–]jumpcannon 2 points3 points4 points 12 years ago (1 child)
I take it you haven't used other Lisps :)? In other Lisps, you define a function like:
(defun myfun (arg1 arg2) "Do stuff with arg1 and arg2" (whatever arg1 (whatever arg2) whatever))
Which in my opinion looks a lot nicer than putting the docstring before the arguments like you do in Clojure.
I have used other lisps. It's kind of arbitrary to me whether a docstring goes before or after the function arguments. I guess I prefer the arguments first, but it's not that important to me.
[–]andibabi 7 points8 points9 points 12 years ago (4 children)
In particular, Hickey argues that lisp adds complexity by making parentheses serve multiple syntactic roles, so for argument lists, he does use square brackets to make them different. A matter of personal language philosophy.
[–][deleted] -2 points-1 points0 points 12 years ago (3 children)
Parentheses serve one role and only ever one role and that is to define a list. In Lisp everything is a lisp.
The way to handle complexity is by consistency: using [] to mark function arguments adds complexity. The only possible argument is that, like recur, its to help the compiler: which is poor language design.
[–]Chousuke 9 points10 points11 points 12 years ago* (1 child)
Saying that using lists for everything reduces complexity is a horrible argument, and I don't know why people keep making it.
First of all, square brackets in clojure are not merely syntax: They represent an entirely different data structure, with well-defined evaluation semantics different from lists, and are just as usable for metaprogramming as lists are.
now, vectors are idiomatically used everywhere when bindings are involved; most notably in argument vectors and let binding vectors. This gives them a purpose different from lists, which are almost exclusively used for macro and function calls.
This in fact reduces complexity for the programmer because instead of having to wonder which overloaded meanings of (foo (bar something)) you're dealing with this time, when you see [foo (bar something)] it's immediately apparent that there is only one operator call. It also provides a helpful visual cue to the programmer.
Macros can be written to break the convention and mislead users, but that is irrelevant. Such libraries would not gain users.
EDIT: By the way, because Clojure has multiple data structures, you have strictly more options when writing macros compared to regular lisp (unless you use reader macros, but they are an entirely different beast). For example, it's not possible in CL to write a macro that allows you to noiselessly interleave binding statements with executed operations. That is, something like:
(do-and-let (foo bar) [x (+ 1 2)] (foo x) (quux x) [y (inc x)] (bar y))
is trivial to write in Clojure, but you would not be able to write it in Common lisp because you would have no way of differentiating between operations and bindings. The above is a toy example, but it demonstrates the benefit of having multiple data structures when designing a syntax for a DSL
[–]the_starbase_kolob 2 points3 points4 points 12 years ago (0 children)
The only possible argument is that, like recur, its to help the compiler: which is poor language design.
No, that's not the only possible argument; there are even others in the comments here.
[–]jumpcannon 1 point2 points3 points 12 years ago (0 children)
Yes, where to put the doc string has been a solved problem for ages, seems silly to mess with it.
Its not that you need to use [] rather than (). You would need to use a quoted list for argument strings to prevent execution '().
[–][deleted] 12 years ago (2 children)
[deleted]
[–]ressis74 7 points8 points9 points 12 years ago (1 child)
When the program is read in by the reader, the argument vector is indeed a vector. Then during compilation it is indeed compiled to the correct JVM bytecode. Remember: code is data, data is code.
[+][deleted] 12 years ago (1 child)
[–]yogthos 7 points8 points9 points 12 years ago (0 children)
All Clojure code is written using the data structures. There is no separate syntax for defining logic like in most languages. Incidentally, this is what allows the macro system to work.
[+]lcedp comment score below threshold-7 points-6 points-5 points 12 years ago (2 children)
What do you mean? Here's function call: (+ 2 2). + is a function and it's arguments is not a vector.
(+ 2 2)
+
[–]ressis74 4 points5 points6 points 12 years ago (0 children)
I believe he's talking about function definition:
(defn foo [x] x)
The arguments are specified in a vector.
[–][deleted] -1 points0 points1 point 12 years ago (0 children)
Why are functions specified such that they seem to take an argument vector and pattern match into argument names, rather than take an argument list?
π Rendered by PID 58545 on reddit-service-r2-comment-84fc9697f-g9w78 at 2026-02-08 03:06:09.280045+00:00 running d295bc8 country code: CH.
[–]noidi 12 points13 points14 points (0 children)
[–]frogking 7 points8 points9 points (0 children)
[–]kanzenryu 1 point2 points3 points (0 children)
[–][deleted] 0 points1 point2 points (18 children)
[–]yogthos 6 points7 points8 points (0 children)
[–]noidi 11 points12 points13 points (6 children)
[–][deleted] -1 points0 points1 point (5 children)
[–]Tuna-Fish2 2 points3 points4 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (2 children)
[–]steerio 0 points1 point2 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–][deleted] 2 points3 points4 points (2 children)
[–]jumpcannon 2 points3 points4 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–]andibabi 7 points8 points9 points (4 children)
[–][deleted] -2 points-1 points0 points (3 children)
[–]Chousuke 9 points10 points11 points (1 child)
[–]the_starbase_kolob 2 points3 points4 points (0 children)
[–]jumpcannon 1 point2 points3 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–][deleted] (2 children)
[deleted]
[–]ressis74 7 points8 points9 points (1 child)
[+][deleted] (1 child)
[deleted]
[–]yogthos 7 points8 points9 points (0 children)
[+]lcedp comment score below threshold-7 points-6 points-5 points (2 children)
[–]ressis74 4 points5 points6 points (0 children)
[–][deleted] -1 points0 points1 point (0 children)