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.
Related
I recently stumbled across this bit of example code in Racket's ffi documentation:
(let-values ([(data meta) (read-sound* "/tmp/x.wav")])
(printf ">>> data-length: ~s\n>>> meta: ~s\n" (length data) meta)
(let* ([data data #;
(list-of (list (add-half (1st x) (1st y))
(add-half (2nd x) (2nd y)))
(x <- data
and
y <- (append (repeated-list (list 0.0 0.0) 11025) data)
and
i <- 0.1 0.12 ..))])
What does x <- data, y <- ... and i <- ... do?
I could not find any relevant documentation for this notation.
Link to the code in question.
First note that #; comments out the following s-expression, so the entire list-of form is commented out in the code sample. Looking at the linked code, note that (require swindle) is also commented out, suggesting that the relevant definitions may be found there.
Looking at the documentation for Swindle, it turns out that the list-of form is a list comprehension facility, and that <- is used in generator clauses here. In particular, (v <- ... and v <- ...) is a parallel generator clause.
I am writing a simple interpreter that should
output: +inf or -inf for the following computations:
(/ 0)
(/ 1 0)
(/ -0)
I notice that replaced 0 by 0.0 gives me the behavior I want.
But I haven't figured out to convert -0 to -0.0.
exact->inexact loses the negative sign.
(exact->inexact -0) gives 0.0.
To do this, with the literal text -0 you would have to change the Reader so that -0 reads equal to -0.0, an inexact version. To be consistent you might want to read every number as an inexact number, whether it has a decimal point or not.
It's worth noting that you can do this by prefixing a number #i, for example #i-0 reads equal to -0.0. However, it sounds like you might want to change the reader so that every number reads the same as if it had #i prefixed onto it including -0.
One of the easier ways to extend the reader is with a readtable. You can make a function that extends a readtable like this:
;; Readtable -> Readtable
(define (extend-readtable orig-rt)
;; Char InputPort Any Nat Nat Nat -> Any
(define (rt-proc char in src ln col pos)
....)
...
(make-readtable orig-rt
#f 'non-terminating-macro rt-proc
...))
To use this to define a #lang language, you need to put the reader implementation in your-language/lang/reader.rkt. Here that's inexact-number/lang/reader.rkt, where the inexact-number directory is installed as a single-collection package (raco pkg install path/to/inexact-number).
inexact-number/lang/reader.rkt
#lang racket
(provide (rename-out [-read read]
[-read-syntax read-syntax]
[-get-info get-info]))
(require syntax/readerr
syntax/module-reader)
;; Readtable -> Readtable
(define (extend-readtable orig-rt)
;; Char InputPort Any Nat Nat Nat -> Any
(define (rt-proc char in src ln col pos)
....)
...
(make-readtable orig-rt
#f 'non-terminating-macro rt-proc))
;; [X ... -> Y] -> [X ... -> Y]
(define ((wrap-reader rd) . args)
(parameterize ([current-readtable (extend-readtable (current-readtable))])
(apply rd args)))
(define-values [-read -read-syntax -get-info]
(make-meta-reader 'inexact-number
"language path"
lang-reader-module-paths
wrap-reader
wrap-reader
identity))
The main work goes into filling in the .... holes in the extend-readtable function. Within the rt-proc, you can have it "peek" into the input port in to see if its a number, and if it is, call the Racket reader on a port that has #i appended to the front of in. You might be able to do this with something like input-port-append:
(input-port-append #f (open-input-string "#i") in)
In the context of extend-readtable, here's some code that does the peeking and re-reading:
;; Readtable -> Readtable
(define (extend-readtable orig-rt)
;; Char InputPort Any Nat Nat Nat -> Any
(define (rt-proc char in src ln col pos)
(define try-in (peeking-input-port in))
(define try (read/recursive try-in char orig-rt))
(cond
[(number? try)
;; read it as if it had #i on the front
(define prefix (string-append "#i" (string char)))
(define inexact-in
(input-port-append #f (open-input-string prefix) in))
(read-syntax/recursive src inexact-in #f orig-rt)]
[else
;; read normally
(read-syntax/recursive src in char orig-rt)]))
(make-readtable orig-rt
#f 'non-terminating-macro rt-proc))
Once you have this done, you should be able to use it like this:
#lang inexact-number racket
-0
; => -0.0
(/ -0)
; => -inf.0
P.S. I have now made #lang inexact-number available on the Racket package server, as the package inexact-number-lang. By the way, there's also #lang exact-decimal, which has the opposite affect of making numbers like 5.2 into exact rational numbers.
This is because -0 in Racket is the same literal datum that can also be written as 0, +0, 0000000, #e0, #e-0/1, -00000/1, or in various other ways. All of these syntaxes produce the very same value from the reader, which is an exact integer. Unlike floating-point numbers, exact numbers don't have signed zeros. To illustrate:
> (exact-integer? 0)
#t
> (exact-integer? +0)
#t
> (exact-integer? -0)
#t
> (eq? +0 -0)
#t
> (eq? -0 0)
#t
To get the behavior you want, you need to adjust the reader layer so that 0 and -0 don't produce the same value. I don't think there is a built-in parameter for doing what you want (there are for many other reader customizations), but you can do it by creating a custom readtable.
I would need more context to give you further guidance (for example, you say you're writing an "interpreter," which isn't the usual way of making a DSL in Racket), but my first inclination would be that, rather than re-implementing number parsing, you might map - to a "non-terminating-macro" and handle the rest in the expander (or interpreter) layer.
-0 doesn't exist! If you enter something silly like (define x -0) and press the Macro stepper #'> before any transformations you'll see it has read it in as (define x 0). The sign is truncated by the reader since integers doesn't have positive and negative zero like IEEE754 does. Thus unless you create your own language with your own reader that can discriminate on signed zero mapped to a data structure that supports it you cannot solve this.
IEEE754 floating points has the sign as it's own bit and thus every number, including 0, can be both positive and negative.
As for Scheme standard: Before R6RS there was no requirement for a full numeric tower and the report even mentions that a floating point only Scheme might be useful. Thus I believe some implementations of R5RS actually might read -0 as -0.0.
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
I defined a generic function taking 2 arguments:
(defgeneric interact (a b))
The order of the arguments should not be important, so (interact x y) and (interact y x) should be the same, but I don't want to define two methods that do the same for every combination of different objects.
A Method-Combination of this type should help:
(defmethod interact :around (a b)
(if (some-function a b)
;;some-function has to be true if (eq (class-of a) (class-of b))
;;else (some-function a b) is (not (some-function b a))
;;similar #'<=
(call-next method)
(interact b a))
But I would have to know #'some-function and be able to know the type of the arguments I have to define.
Edit: both proposed approaches have a few limitations discussed in the comments below. Please read them before using this answer!
Can I suggest two options - a working but hacky option for when you only have two arguments, and a vaguely sketched out generic approach which I think should work but I haven't written:
Option 1:
(defparameter *in-interact-generic-call* nil)
(defgeneric interact (x y))
(defmethod interact ((x T) (y T))
; this can be called on pretty much anything
(if *in-interact-generic-call*
(cause-some-kind-of-error) ; Replace this with a more sensible error call
(let ((*in-interact-generic-call* T))
(interact y x))))
(defmethod interact ((x integer) (y string))
; example
(print x )(prin1 y))
(interact 5 "hello") ; should print 5 "hello"
(interact "hello" 5) ; should print 5 "hello"
;(interact "hello" "hello") ; should cause an error
Essentially the idea is to define a generic function which always matches anything, use it to try to swap the arguments (to see if that matches anything better) and if it's already swapped the arguments then to raise some kind of error (I've not really done that right here).
Option 2
Define the generic function as something like interact-impl. Actually call the standard function (defined by defun) interact.
In interact, define a loop over all permutations of the order of your arguments. For each permutation try calling interact-impl (e.g. using (apply #'interact-impl current-permutation).)
At least in sbcl, no matching arguments gives me a simple-error. You probably would want to do a more detailed check that it's actually the right error. Thus the code in interact looks something like
; completely untested!
(do (all-permutations all-permutations (cdr all-permutations))
(...) ; some code to detect when all permutations are exhausted and raise an error
(let (current-permutation (first all-permutations))
(handler-case
(return (apply #'interact-impl current-permutation))
(simple-error () nil)) ; ignore and try the next option
)
)
So what you are looking for is an arbitrary linear order on the class objects.
How about string order on class names?
(defun class-less-p (a b)
"Lexicographic order on printable representation of class names."
(let* ((class-a (class-of a))
(name-a (symbol-name class-a))
(pack-a (package-name (symbol-package name-a)))
(class-b (class-of b))
(name-b (symbol-name class-b))
(pack-b (package-name (symbol-package name-b))))
(or (string< pack-a pack-b)
(and (string= pack-a pack-b)
(string<= name-a name-b)))))
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.