printing with format is printing quotation marks? - f#

When I run printfn "hello", the outcome is hello (without quotation marks). However, when I run
let mystring = "hello"
printfn "%A" mystring
the outcome is "hello" (with quotation marks). Why is this and how can I then print with a format/parameter without having quotation marks appear?

printfn "%s" "hello"
Here is the
Documentation
and another helpful
link

Related

How can I wrap sprintf + a call into a single function, and have two signatures, in F#?

I have a function that takes a string and sends it to a terminal:
Print: string -> unit
it is passed to several modules that do this, to simplify the syntax
// printing
let print = settings.Print
and then it's used like that:
print "hello"
print (sprintf "the time is %A" DateTime.UtcNow)
my question is: Can I make two functions, with the same name but two signatures, so I could use it to either print a string, or a sprintf, then print the string.
for example:
print "hello"
print "the time is %A" DateTime.UtcNow
Is this possible? the goal is to simplify the syntax as a lot of code is peppered with info being sent to the terminal (which is currently a Telegram channel)
You can use kprintf for this:
let myPrint s = printfn "My print: %s !" s
let print x = Printf.kprintf myPrint x
print "%d" 1
print "aaaa"
print "%s %s" "b" "c"
There are some examples here and here.
I couldn't find kprintf documentation, so I'm not sure that this usage is correct, but it produces the correct result for me. Another possible candidate is ksprintf, which also produces the same result.
You can use the same signature as sprintf:
let print (format : Printf.StringFormat<'T>) =
sprintf format
|> dosomethingElse
and you can use it as you want:
print "hello"
print "the time is %A" DateTime.UtcNow

F# - printfn Guid

I have following printing example in F#
for row in data.Rows do
printfn "Example: (%s)" row.A
But I received this error
Script1.fsx(15,67): error FS0001: This expression was expected to have
type
string but here has type
Guid
I didn't find any example of printing of Guid type.
I tried apply ToString() method to row.A but it is not working as well
There are two options here:
for row in data.Rows do
printfn "Example: (%s)" (row.A.ToString())
or
for row in data.Rows do
printfn "Example: (%A)" row.A
Here the %A can be used for any type and the compiler will automatically print it for you
You can use %A for a Guid, like this:
printfn "Example: (%A)" row.A
When using %s, the type must be a string.
The MSDN Documentation has more information about which format type to use and how it behaves.
In addition to the answers already given, it's worth noting that Guid also supports an overload of ToString, giving you the option to control how the GUID string is formatted.
You could, for example, write it out like this:
printfn "Example: (%s)" (row.A.ToString "n")
if you want to omit the hyphens (Example: (78e6fb89dc5045988d445c4d8aef4e28)).
Or you could use stringf for this, if you want an alternative with pipes instead of parentheses:
row.A |> stringf "n" |> printfn "Example: (%s)"
or if you don't need the formatting option:
row.A |> string |> printfn "Example: (%s)"

No input from F# printf

I am going through the "Try F#" tutorial and decided that I wanted to try writing the code in the editor to Visual Studio once I installed the necessary F# plugins.
The code is:
let toHackerTalk (phrase:string) =
phrase.Replace("t", "7").Replace("o", "0")
let name:string = "tom"
printf "%s",toHackerTalk name
The code runs on the online editor, but when I try running it on Visual Studio all it does is flash the command prompt asking me to press a key to continue. I realize that this must be a very basic question, I just can't see what the problem could be since it runs perfectly fine in the online editor.
Your printf line should look like this:
printf "%s" (toHackerTalk name)
Otherwise, you are creating a tuple instead of calling printf.
you should do:
printf "%s" (toHackerTalk name)
see demo: https://dotnetfiddle.net/Ft9O4z
because with F# you dont need to separate function parameters with comma, comma is used for tuples:
let d = printf "%s",toHackerTalk name
printfn "%A" d // (<fun:d#6>, "70m")
you are creating a tuple with two values ( (printf "%s"), (toHackerTalk name) ):
printf "%s" // a function string -> unit
"70m" // a string
you dont get error because you are creating a tuple, who is ignored (maybe you get a warning asking to ignore value)
you cannot do
printf "%s" toHackerTalk name
because this mean call printf with 3 args:
"%s" a string
toHackerTalk a function string -> unit
name a string
and printf "%s" expect only 1 string arg
so you need to do
printf "%s" (toHackerTalk name) to execute toHackerTalk name and pass result as argument
is the same as
let temp = toHackerTalk name // or (toHackerTalk name) parens are optional
printf "%s" temp

printfn "%A" "c" using F#

By running printfn "%A" "c", I get "c".
By running printfn "%s" "c", I get c.
Why the difference? The same goes for char.
The %A specifier tries to hint at object types - the "c" is it trying to show it is a string. When you do %s the compiler knows you want to print a string so it doesn't print the quotes
Because printfn "%A" uses reflection, it displays results the same as values automatically printed out by F# Interactive. On the other hand, %s is for strings only, and it shows contents of strings.
The generic case of "%s" is "%O" when ToString methods are used. The %A specifier is slow, but helpful for structural types and types without overridden ToString methods.

Newlines and formatters

I recently got bit by becoming complacent writing things like
printf "\n%f\n" 3.2
instead of
printf "%s%f%s" Environment.NewLine 3.2 Environment.NewLine
My question is: is there any way to write the safe second version as nicely as the first (i.e. a special character in the format string which inserts Environment.Newline so that an argument for each newline instance in the format string isn't required)?
How about using kprintf for a double pass, replacing \n with NewLine:
let nprintf fmt = Printf.kprintf (fun s -> s.Replace("\n", Environment.NewLine) |> printf "%s") fmt
Then in nprintf "\n%f\n" 3.2 all \n get replaced by NewLine.
There's not an escape sequence, but you could shorten it:
[<AutoOpen>]
module StringFormatting =
let nl = System.Environment.NewLine
//Usage
printfn "%s%f%s" nl 3.2 nl
Here is the list of character escapes on MSDN.
As an aside, I wonder what this would do:
printfn #"
%f
" 3.2

Resources