#| xwindows and I were talking about lisp in contrast to perl. I gave an example of the loop facility for writing alternate runs of bytes. |# (loop repeat 8000 do (loop for no in '(#xab #xcd) do (write-byte no *standard-output*))) #| which is expressive in that the meaning is very clear (once we get that single quote has no relation to strings) From here, some of the perfectly real and practical examples I gave were too jokey so I am revisiting string concatenation here. There are a few different ways and it's a bit difficult to choose a right one. |# (defparameter string1 "foo") (defparameter string2 "bar") #| Actually the best way to do special scope assignment is a topic as well. |# (print (concatenate 'string string1 string2)) #|"foobar" Has a clear meaning, and works for any number of strings, and would work for 'list as well for that matter. |# (print (with-output-to-string (string) (princ string1 string) (princ string2 string))) #|"foobar" This is a popular one that often compiles well, making an output stream that gets converted to a string of what it received. Sometimes we shadow *standard-output* so we can princ with the default stream argument: |# (print (with-output-to-string (*standard-output*) (princ string1) (princ string2))) #|"foobar" however these aren't even trying to play in terms of perl's economy of code characters. In lisp we can easily extend the language with a new reader macro. for #{ .. } |# (defun paste-strings (s c n) (declare (ignore c n)) (loop for string = (read s) for peek = (peek-char nil s) collecting string into strings while (not (char= peek #\})) finally (read-char-no-hang s) (return `(concatenate 'string ,@strings)))) (set-dispatch-macro-character #\# #\{ #'PASTE-STRINGS) (print #{ "foo" "bar" "baz"}) #|"foobarbaz" If this was a major goal, you could add this dispatch macro to the image, and use that saved image/core when expecting to concatenate a lot of strings. |# #| reuse? as a shell util? (sb-ext:save-lisp-and-die "paste" :executable t) .. $ ./paste --noprint <out.txt (princ #{ "foo" "bar" "baz" }) EOG $ cat out.txt foobarbaz Note the image can be re-entered, extended, and different versions saved. |# #| princ princs the human-friendly form of an object. "foobar" -> foobar This is in contrast to print and prin1 which print the lisp READable form of the object. "foobar" -> "foobar" |# #| SMALL GOTCHA since curlies are unused in lisp, they are valid characters in a variable name. This means my reader macro will misunderstand: (defparameter s1 "foo") #{s1 s1} } .... it didn't stop reading? it finds two supposed variable names, s1 and s1} . So there must be whitespace separating variable names from the closing }. #{s1 s1 } in contrast, this is fine: #{s1 s1 ""} |# #|PS I actually didn't use/know about --noprint's strange behaviour of usefully collecting *standard-output* and eventually printing it. Thanks xwindows ! |#