all
I want to change a element to formatted string, then I use format function. (the language I use is scheme )
As the document in http://www.gnu.org/software/mit-scheme/documentation/mit-scheme-ref/Format.html said, I can use ~mincolA if I want inserts spaces on the right.
So I use
(format "~4A " x)
but I get an error like that:
format: ill-formed pattern string
explanation: tag `~4' not allowed
pattern string: "~4A "
I want to get the result like below:
if x is 0, then the result is space space space 0;
if x is 12, then the result is space space 12.
I know I can use
(string-append (make-string (- 4 (string-length x)) #\ ) x)
to get the result I want, but I really want use "format" function.
Thanks.
Notice that the referenced documentation is for MIT/GNU Scheme, the format function works different in Racket. Out-of-the-box, you can use the ~a function for the same effect:
(~a x #:min-width 4 #:align 'right #:left-pad-string " ") ; x can be a number or a string
For example:
(~a 0 #:min-width 4 #:align 'right #:left-pad-string " ")
=> " 0"
(~a "12" #:min-width 4 #:align 'right #:left-pad-string " ")
=> " 12"
If you don't mind importing an additional external library, #uselpa's answer is spot-on.
You can use the format procedure from SRFI 48:
> (require srfi/48)
> (format "~4F" 0)
" 0"
> (format "~4F" 12)
" 12"
If you want to keep the original format procedure along with this one, you can give the one from SRFI 48 a prefix:
> (require (prefix-in srfi48: srfi/48))
> (srfi48:format "~4F" 0)
so the original format is still available.
Scheme doesn't have a format procedure, but one is available in SRFI-48. It is not compatible with either MIT Scheme nor #!racket (the language).
#!r6rs
(import (rnrs base)
(srfi :48))
(format "~4F " "x") ; ==> " x"
You can use SRFI-48 with #!racket in similar manner:
#!racket
(require srfi/48)
(format "~4F " "x") ; ==> " x"
F works only for numbers and strings according to the documentation:
~[w[,d]]F Fixed ~w,dF outputs a number with width w and d digits
after the decimal; ~wF outputs a string or number with width w.
Also by evaluating (format "~h") you get instructions for use so for the basic reminder on syntax you don't need to visit the SRFI page.
Related
I would like to dynamically create a list of chars to use with read-char-choice. From this answer of similar question, how to construct the list programmatically with unquoted values as choices, ?1 with a function. The function that I ended up is
(defun prompt-list (name-list)
"docstring"
(let ((names name-list)
(name-num 1)
(choice-list (list)))
(dolist (x names)
(add-to-list 'choice-list
`(,name-num ;; in that part how to create the ?1, ?2 but dynamically
,x (lambda () (setq project-headers x))))
(setq name-num (+ 1 name-num)))
choice-list))
when I try to run it it returns error : Format specifier doesn’t match argument type.
In my understanding it need a char type, so my question is how to produce char types programmatically?
?1 is the read syntax for the character '1', which has the integer value 49. You can use the read syntax to initialize your name-num variable, rather than using the integer 1:
(defun prompt-list (name-list)
"docstring"
(let ((names name-list)
(name-num ?1)
(choice-list (list)))
(dolist (x names)
(add-to-list 'choice-list `(,name-num
,x (lambda () (setq project-headers ',x)))
t)
(setq name-num (+ 1 name-num)))
choice-list))
A couple of things to note:
You want the use ,x when setting project-headers, not just x, as the latter won't be valid by the time the lambda is invoked.
You want to append to choice-list as you build it, which is what the final t argument to add-to-list above does, otherwise your read-char-choice prompt will be in reverse order.
I am looking for a way to output a character
a number of times using format. Is this possible? Can someone fill
in the _?_'s, so that the example works?
(let ((n 3))
(format nil "_?_" _?_ #\* _?_ ))
should return
=> "***"
It's nice to see so many solutions: ~A, ~<, and ~{ so far.
The ~#{ iteration construct provides a concise solution:
(format nil "~v#{~A~:*~}" 3 #\*)
(format nil "~a~:*~a~:*~a~:*" #\*)
"***"
Or elaborating a bit on Joshua Taylor's answer:
(format nil "~v{~a~:*~}" 3 '(#\*))
Would be one way of doing this. Don't be confused by the asterisks in the format directive, they are control characters, not characters being printed.
In terms of efficiency, however, this:
(make-string 3 :initial-element #\*)
would be a preferred way to achieve the same effect.
If you use the ~A directive, you can get this in exactly the form that you suggested, i.e.,
(let ((n 3))
(format nil "_?_" _?_ #\* _?_ ))
with three format arguments. However, if you use ~<, you can actually do this with just two format arguments. If you don't need this string inside of some other string that's already being generated by format, you could also just make the string using make-string.
Using Tilde A (~A)
You could print the character and specify a minimum width and the same character as the padding character. E.g., using ~v,,,vA and two arguments, you can ensure that some number of characters is printed, and what the padding character is.
CL-USER> (let ((n 3))
(format nil "~v,,,vA"
n ; number of characters that must be printed
#\* ; character to use as padding
#\*)) ; character to print with ~A
"***"
CL-USER> (let ((n 3))
(format nil "~v,,,vA" n #\* #\*))
"***"
CL-USER> (let ((n 10))
(format nil "~v,,,vA" n #\* #\*))
"**********"
This uses the full form of ~A:
~mincol,colinc,minpad,padcharA is the full form of ~A, which allows
control of the padding. The string is padded on the right (or on the
left if the # modifier is used) with at least minpad copies of
padchar; padding characters are then inserted colinc characters at a
time until the total width is at least mincol. The defaults are 0 for
mincol and minpad, 1 for colinc, and the space character for padchar.
as well as v:
In place of a prefix parameter to a directive, V (or v) can be used.
In this case, format takes an argument from args as a parameter to the
directive. The argument should be an integer or character. If the arg
used by a V parameter is nil, the effect is as if the parameter had
been omitted. # can be used in place of a prefix parameter; it
represents the number of args remaining to be processed. When used
within a recursive format, in the context of ~? or ~{, the # prefix
parameter represents the number of format arguments remaining within
the recursive call.
Using Tilde Less Than (~<)
There's also a less commonly used format directive, tilde less than, that's used for justification. it takes a format string and makes s
~mincol,colinc,minpad,padchar<str~>
This justifies the text produced by processing str within a field at
least mincol columns wide. str may be divided up into segments with
~;, in which case the spacing is evenly divided between the text
segments.
We can (ab)use this by passing an empty format string and just specifying the width and the padding character:
CL-USER> (let ((n 3))
(format nil "~v,,,v<~>"
n ; width
#\*)) ; padding character
"***"
CL-USER> (let ((n 5))
(format nil "~v,,,v<~>" n #\*))
"*****"
Just make a string
Of course, unless you need this special string inside of some other string that you're already formatting, you should do what wvxvw suggested, and just use make-string:
(make-string 3 :initial-element #\*)
Other alternatives
format is very flexible, and as this and other answers are pointing out, there are lots of ways to do this. I've tried to stick to ones that should do this in one pass and not do explicit iterations, but this can be done with format iterations, too, as Lars Brinkhoff and wvxvw have pointed out.
Like the answer of Lars, but we write the character wih ~C, instead of using the printer with ~A:
(format nil "~v#{~C~:*~}" 3 #\*)
Writing a character with something like write-char is a simpler operation than printing a Lisp object. The printer has a lot of context to observe and has to find the right way to print the object. OTOH, something like WRITE-CHAR just writes a single character to a stream.
I'm trying to create a function that will take a string and display it.
(defun closing (s)
(format t "~{~a~}" ("Sincerely," "\n" s)))
What I hope to get is
Sincerely,
Frank
if "Frank" is the string I passed in. It complains of the variable S is defined but never used. What am I doing wrong?
Trying to use format alone: If I declare urname as a defparameter to be "Frank", the following doesn't print Frank, rather just the variable name. (Without quote it complains of urname not being a function.)
(format t "~{~a~}" '(urname urname urname))
How can I feed variables to format?
There are three issues here: (1) The code you posted doesn't just have the problem of not using s; it's also trying to call the string "Sincerely" as a function; (2) quoting a list means you'll get exactly what's quoted (e.g., a list of symbols, not a list of values of variables); (3) calling format with lists.
(something other-stuff...) is a function call
When I put the code you posted into SBCL, I get some very specific and helpful output:
CL-USER> (defun closing (s)
(format t "~{~a~}" ("Sincerely," "\n" s)))
; in: DEFUN CLOSING
; ("Sincerely," "n" S)
;
; caught ERROR:
; illegal function call
; (SB-INT:NAMED-LAMBDA CLOSING
; (S)
; (BLOCK CLOSING (FORMAT T "~{~a~}" ("Sincerely," "n" S))))
;
; caught STYLE-WARNING:
; The variable S is defined but never used.
;
; compilation unit finished
; caught 1 ERROR condition
; caught 1 STYLE-WARNING condition
("Sincerely," "\n" s) is an illegal function call, since a string, like "Sincerely", can't have a function binding. Since SBCL sees the problem in that, it recognizes that the one thing that s might have been used for (i.e., an argument to a function call), can't happen. That's why you'll get the error, and then the associated style warning.
Creating lists of values
The second is probably answered in other questions already, but the short answer is that you want (list x y z), not '(x y z). The former calls the function list with the values of the variables x, y, and z, while the latter denotes a literal list of the symbols x, y, and z.
CL-USER> (let ((a 42)
(b 89))
(print '(a b)) ; a list of two symbols
(print (list a b))) ; a list of two numbers
(A B)
(42 89)
Format, iteration, &c.
The third is probably more interesting, since format has so many possibilities. The ~{ and ~} in your example are used for iterating over values in a list. First, let's look at a simple example: you can just use the format directive ~a and call format with the arguments you want to splice in:
CL-USER> (let ((closing "Sincerely")
(name "Frank"))
(format t "~a,~%~a" closing name))
Sincerely,
Frank
Now, if you need to print multiple values, you can use ~{ and ~} to have format iterate over a list of values:
CL-USER> (let ((closing "Sincerely")
(names '("Frank" "John")))
(format t "~a,~{~%~a~}" closing names))
Sincerely,
Frank
John
If the names are the values of variables, then you can either create a list containing those values:
CL-USER> (let ((closing "Sincerely")
(name1 "Frank")
(name2 "John"))
(format t "~a,~{~%~a~}" closing (list name1 name2)))
Sincerely,
Frank
John
or you can change ~{ to ~#{ and have format read the remaining arguments as the list:
CL-USER> (let ((closing "Sincerely")
(name1 "Frank")
(name2 "John"))
(format t "~a,~#{~%~a~}" closing name1 name2))
Sincerely,
Frank
John
You should read a tutorial about format, from here for example
For an easy explanation
(format
(destination-stream usually t for standard output nil to form a string)
(here comes the string)
(&rest variables that should write in the string where is an ~A and by position like String.format in java or c))
in your case, you need the symbol ~% or use the character for return in common lisp
CL-USER> (defun closing (s) (format t "~A~%~%~A" "Sincerely," s))
CLOSING
CL-USER> (closing "paco")
Sincerely,
paco
NIL
The nil say that the functions returns null, and the other is the standard output if you want to return a string, put nil instead of t
How do you get a printf %6.2f in scheme or racket, as you would in C?
Right now all I have is printf "The area of the disk is ~s\n" ( - d1 d2), but I can't format the output to a specific floating point format.
Thanks
To get a behavior closer to C's printf() function use the format procedure provided by SRFI-48, like this:
(require srfi/48)
(format "The area of the disk is ~6,2F~%" (- d1 d2))
A more verbose alternative would be to use Racket's built-in ~r procedure, as suggested by #stchang:
(string-append
"The area of the disk is "
(~r (- d1 d2) #:min-width 6 #:precision '(= 2))
"\n")
Racket has ~r.
You'll probably want to provide #:min-width and #:precision arguments.
I am looking for a way to output a character
a number of times using format. Is this possible? Can someone fill
in the _?_'s, so that the example works?
(let ((n 3))
(format nil "_?_" _?_ #\* _?_ ))
should return
=> "***"
It's nice to see so many solutions: ~A, ~<, and ~{ so far.
The ~#{ iteration construct provides a concise solution:
(format nil "~v#{~A~:*~}" 3 #\*)
(format nil "~a~:*~a~:*~a~:*" #\*)
"***"
Or elaborating a bit on Joshua Taylor's answer:
(format nil "~v{~a~:*~}" 3 '(#\*))
Would be one way of doing this. Don't be confused by the asterisks in the format directive, they are control characters, not characters being printed.
In terms of efficiency, however, this:
(make-string 3 :initial-element #\*)
would be a preferred way to achieve the same effect.
If you use the ~A directive, you can get this in exactly the form that you suggested, i.e.,
(let ((n 3))
(format nil "_?_" _?_ #\* _?_ ))
with three format arguments. However, if you use ~<, you can actually do this with just two format arguments. If you don't need this string inside of some other string that's already being generated by format, you could also just make the string using make-string.
Using Tilde A (~A)
You could print the character and specify a minimum width and the same character as the padding character. E.g., using ~v,,,vA and two arguments, you can ensure that some number of characters is printed, and what the padding character is.
CL-USER> (let ((n 3))
(format nil "~v,,,vA"
n ; number of characters that must be printed
#\* ; character to use as padding
#\*)) ; character to print with ~A
"***"
CL-USER> (let ((n 3))
(format nil "~v,,,vA" n #\* #\*))
"***"
CL-USER> (let ((n 10))
(format nil "~v,,,vA" n #\* #\*))
"**********"
This uses the full form of ~A:
~mincol,colinc,minpad,padcharA is the full form of ~A, which allows
control of the padding. The string is padded on the right (or on the
left if the # modifier is used) with at least minpad copies of
padchar; padding characters are then inserted colinc characters at a
time until the total width is at least mincol. The defaults are 0 for
mincol and minpad, 1 for colinc, and the space character for padchar.
as well as v:
In place of a prefix parameter to a directive, V (or v) can be used.
In this case, format takes an argument from args as a parameter to the
directive. The argument should be an integer or character. If the arg
used by a V parameter is nil, the effect is as if the parameter had
been omitted. # can be used in place of a prefix parameter; it
represents the number of args remaining to be processed. When used
within a recursive format, in the context of ~? or ~{, the # prefix
parameter represents the number of format arguments remaining within
the recursive call.
Using Tilde Less Than (~<)
There's also a less commonly used format directive, tilde less than, that's used for justification. it takes a format string and makes s
~mincol,colinc,minpad,padchar<str~>
This justifies the text produced by processing str within a field at
least mincol columns wide. str may be divided up into segments with
~;, in which case the spacing is evenly divided between the text
segments.
We can (ab)use this by passing an empty format string and just specifying the width and the padding character:
CL-USER> (let ((n 3))
(format nil "~v,,,v<~>"
n ; width
#\*)) ; padding character
"***"
CL-USER> (let ((n 5))
(format nil "~v,,,v<~>" n #\*))
"*****"
Just make a string
Of course, unless you need this special string inside of some other string that you're already formatting, you should do what wvxvw suggested, and just use make-string:
(make-string 3 :initial-element #\*)
Other alternatives
format is very flexible, and as this and other answers are pointing out, there are lots of ways to do this. I've tried to stick to ones that should do this in one pass and not do explicit iterations, but this can be done with format iterations, too, as Lars Brinkhoff and wvxvw have pointed out.
Like the answer of Lars, but we write the character wih ~C, instead of using the printer with ~A:
(format nil "~v#{~C~:*~}" 3 #\*)
Writing a character with something like write-char is a simpler operation than printing a Lisp object. The printer has a lot of context to observe and has to find the right way to print the object. OTOH, something like WRITE-CHAR just writes a single character to a stream.