4 ms·
One thing that puts me off about Common Lisp is functions that do multiple different things depending on a flag passed to them. (format nil s) formats a string,
by xigoi 4y ago
One thing that puts me off about Common Lisp is functions that do multiple different things depending on a flag passed to them. (format nil s) formats a string, whereas (format t s) formats a string and prints it to stdout. This doesn't look like good design.
- medo-bear 4y agoformat is not just a function. it is a domain specific language. it even has a wikipedia entry, all its own. Like it or not, nothing similar exists in any other language https://en.m.wikipedia.org/wiki/Format_(Common_Lisp) https://en.m.wikipedia.org/wiki/Format_(Common_Lisp)
- xigoi 4y ago> format is not just a function. The article you linked literally starts with: > Format is a function in Common Lisp…
- nequo 4y ago"Not just a function" does not mean that it is "not a function." But I agree with your original point. "format" is not the most descriptive name for something that "formats and maybe prints."
- gumby 4y ago> Like it or not, nothing similar exists in any other language Uh, what? It's not that different from the printf metalanguage (more powerful, sure, but not that different and inspired by printf)
- medo-bear 4y ago> 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-extensible-format-strings.html?m=1 https://arcanesentiment.blogspot.com/2009/02/value-of-extens...
- smcn 4y agoIt makes sense when you understand what it's asking you for. That first argument is you specifying an output destination. For example, would you like to write to an open file, to an open port, to whatever you want. Specifying `t` is the current standard output, whereas nil is you saying "no, just give me the string". Also, `(format t "str")` does not return a string. At least not on SBCL or CCL.
- medo-bear 4y agothats right. the spec states that if destination is non-nil then format returns nil. otherwise a string http://www.lispworks.com/documentation/lw50/CLHS/Body/f_format.htm#:~:text=Description%3A,kind%20of%20formatting%20is%20desired http://www.lispworks.com/documentation/lw50/CLHS/Body/f_form....
- xigoi 4y agoStill, why not have a function that formats a string and another that outputs it somewhere, instead of one that does two unrelated things?
- atakan_gurkan 4y agoSimply, because they are not unrelated. It would be duplication to have two separate functions to do two tasks that have so much in common.
- xigoi 4y agoWhat does formatting a string and sending a string to a file have in common?
- atakan_gurkan 4y agoI was replying to your original post, did not notice you posted something different here. Formatting a string and then either returning it or sending it to stdout (or any other stream) has too much in common. The work is done in the formatting, sending is just an after thought. 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.
- kazinator 4y agoThere is a rhyme and reason to it. There is a stream argument, with the convention that if NIL is used, the stream is an implicit string output stream created for that call, such that the string is returned. And if T is used, then it's a shorthand for standard output. The argument may also be a string with a fill pointer. This convention isn't just in format. It has a name, stream designator: http://www.lispworks.com/documentation/lw50/CLHS/Body/26_glo_s.htm#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_d.htm#designator 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_s.htm#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).
- kagevf 4y ago> (mapcar 'list) 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 ...
- 4y ago
- lispm 4y ago> (format t s) formats a string and prints it to stdout FORMAT runs a domain specific language, which causes various print operations to an output stream.
- agumonkey 4y agothis one is particularly strange but it seems cultural, scheme also works the same for printf debugging it's one more parameter you don't wanna type :)
- dreamcompiler 4y agoWe're talking about I/O here, so we're already outside the domain of functional programming: It's necessary to specify where the output is supposed to go, and that's what format's first argument is for. 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.