This convention isn't just in format. It has a name, stream designator:
http://www.lispworks.com/documentation/lw50/CLHS/Body/26_glo...
Other functions like write support the convention.
Moreover there is a broader designator concept at play: there are other kinds of designators.
http://www.lispworks.com/documentation/lw50/CLHS/Body/26_glo...
A designator is some object that by convention stands for another one, under the semantics of some function.
For instance, functional arguments may be function objects or symbols: (mapcar #'list ...) or (mapcar 'list). The list symbol isn't a function, it's a symbol; the reason you can use it as a function is that it's accepted as a function designator. When you call a symbol as a function, it is resolved to the function via its global function binding.
Another kind of designator is the spreadable argument list designator: http://www.lispworks.com/documentation/lw50/CLHS/Body/26_glo... Some functions use this to take a single object or a list in the same argument position. It makes the functions nicer to use in the case when there is just one object, not having to specify the argument as (list arg).
Thank you for sharing that, I didn't know that was possible.
I also tried just doing 'list at the repl, and sure enough it gets recognized as a function.
I thought I could break it by doing this:
(let ((list (list 1 2 3)))
(mapcar 'list list))
I even tried adding on (funcall 'list list) to that block and it still works the same as if I had used (funcall #'list list) ....I guess it works because the list I bound in the LET isn't referenced as a symbol so FUNCALL etc can distinguish one as a symbol that has a function and the other as the name of a binding ...
Was not expecting these results, so I'll need to review symbols and namespaces ...
Because of separate namspaces, you can't break this either:
(let ((list '(1 2 3)))
(mapcar #'list ...))
But the following will break it: (flet ((list (x) 42))) ;; actually this is undefined behavior: see below
(mapcar #'list ...))
#'list is (function list) which is lexically resolved, and so it refers to the local function flet. If we use 'list, that is unaffected; it goes to the global one.This is a bad example because redefining the standard list function in any scope is not well defined behavior. Implementations can allow it or diagnose it. Because it's undefined behavior, implementations don't have to worry about breakage of list uses which occur in macro expansions. E.g. if the syntax `(,foo ,bar) happens to compile to (list foo bar), and your redefinition of list has taken effect in that scope, then that syntax has broken. Oops!
Ah, OK, I think that's the key part I was missing ... that explanation also accounts for what I saw in the REPL ... thanks again! :)
Also, `(format t "str")` does not return a string. At least not on SBCL or CCL.
http://www.lispworks.com/documentation/lw50/CLHS/Body/f_form....
It executes a program in a domain specific language which creates output to a stream.
This does a bunch of operations. The print functions are being executed on an output stream. If the ARG is NIL, then FORMAT creates a string output stream and later returns the generated string.
(format nil "~a" 3)
is just short for: (with-output-to-string (stream)
(format stream "~a" 3))
~a is then an operation which writes the argument 3 to the output stream.In a sense, this is similar to the parentheses and the prefix notation: it can be distracting if you are not used to it, but after a while it becomes very convenient.
And I do not mean to sound snobbish, but you can easily write a couple macros to have different syntax for these two tasks if it really bothers you.
A point I try to stress with new CL programmers is that if you write new I/O functions to expect a stream designator they're much more flexible than if they expect a pathname.
If you want purely functional string creation, #'format can handle that by passing it nil as its "where" argument.
In both cases #'format does the same thing; the only difference is where the output goes. If #'format knows it's operating non-functionally it can avoid consing up a string and send its output directly to the destination. So it's not necessarily the case that (format t s) creates a string at all.
Uh, what? It's not that different from the printf metalanguage (more powerful, sure, but not that different and inspired by printf)
bit of an understatement. it is an almost turing complete version of printf.
https://arcanesentiment.blogspot.com/2009/02/value-of-extens...
The article you linked literally starts with:
> Format is a function in Common Lisp…
But I agree with your original point. "format" is not the most descriptive name for something that "formats and maybe prints."
for printf debugging it's one more parameter you don't wanna type :)
FORMAT runs a domain specific language, which causes various print operations to an output stream.