Pretty-Printing of F# DU does not work - f#

I am struggling with pretty-printing (%A) this DU.
The local instr is of the type ILInstr.
I would have expected sprintf "%A" instr to result in I_stloc 0us, but as you can see in the locals window (please see instr_str_A), it just shows the typename.
All three different format strings(%A, %O, .ToString()) result in the same output.
What am I doing wrong?
I then tried it in interactive with a simpler DU, but that works:
> type Contact = Email of string | Phone of int
let email = Email "bob#example.com"
printfn "%A" email // nice
printfn "%O" email // ugly!
;;
Email "bob#example.com"
FSI_0002+Contact+Email
A few things which may or may not be relevant:
The DU is private
This is inside VisualFSharp/Microsoft.FSharp.Compiler
Following, it uses the proto-compiler, not the regular compiler. Is the proto-compiler maybe not feature-complete?

Related

Converting a tuple to a string in erlang language

Tuple={<<"jid">>,Member},
Tuple_in_string=lists:flatten(io_lib:format("~p", [Tuple])),
it gives output as:
"{<<\"jid\">>,\"sdfs\"}"
But i want this output without these slashes like
"{<<"jid">>,Member}"
Any pointers?
I have tried all the answers but at the end with io:format("\"~s\"~n", [Tuple_in_string]). what am geeting is "{<<"jid">>,Member}" but it is not a string.it is a atom.I need string on which i can apply concat operation.Any pointers?
You can print it like this:
io:format("\"~s\"~n", [Tuple_in_string]).
It prints:
"{<<"jid">>,"sdfs"}"
The \ are here to denote that the following " is part of the string and not a string delimiter. they do not exist in the string itself. They appear because you use the pretty print format ~p. If you use the string format ~s they wont appear in the display.
1> io:format("~p~n",["a \"string\""]).
"a \"string\""
ok
2> io:format("~s~n",["a \"string\""]).
a "string"
ok
3> length("a \"string\""). % is 10 and not 12
10
Firstly, you don't need to flatten the list here:
Tuple_in_string=lists:flatten(io_lib:format("~p", [Tuple])),
Erlang has the concept of iodata(), which means that printable things can be in nested lists and most functions can handle them, so you should leave only:
Tuple_in_string = io_lib:format("~p", [Tuple]),
Secondly, when you use ~p, you tell Erlang to print the term in such way, that it can be copied and pasted into console. That is why all double quotes are escaped \". Use ~s, which means "treat as string".
1> 38> Tuple = {<<"jid">>,"asdf"}.
{<<"jid">>,"asdf"}
2> IODATA = io_lib:format("~p", [Tuple]).
[[123,[[60,60,"\"jid\"",62,62],44,"\"asdf\""],125]]
3> io:format("~s~n", [IODATA]).
{<<"jid">>,"asdf"}
ok
L = Packet_in_tuple_form={xmlel,<<"message">>,[{<<"id">>,<<"rkX6Q-8">>},{<<"to">>,<<"multicast.devlab">>}],[{xmlel,<<"body">>,[],[{xmlcdata,"Hello"}]},{xmlel,<<"addresses">>,[{<<"xmlns">>,<<"http://jabber.org/protocol/address">>}],[{xmlel,<<"address">>,[{<<"type">>,<<"to">>},"{<<\"jid\">>,\"sds\"}",{<<"desc">>,"Description"}],[]}]}]}.
Gives me:
{xmlel,<<"message">>,
[{<<"id">>,<<"rkX6Q-8">>},{<<"to">>,<<"multicast.devlab">>}],
[{xmlel,<<"body">>,[],[{xmlcdata,"Hello"}]},
{xmlel,<<"addresses">>,
[{<<"xmlns">>,<<"http://jabber.org/protocol/address">>}],
[{xmlel,<<"address">>,
[{<<"type">>,<<"to">>},
"{<<\"jid\">>,\"sds\"}",
{<<"desc">>,"Description"}],
[]}]}]}
The \ in the address field are escape characters.
You can verify the same by checking the length of string.

carriage return character in fsharp

Why does a carriage return character not appear in a F# string literal bound like this
let hw = #"hello
world";;
whereas in C# the following string does contain a carriage return character?
var s2 = #"hello
world";
Thanks
In fact, it is quite easy to spot that the behavior of F# and C# compilers do not differ: being run thru FSC the following
[<EntryPoint>]
let main argv =
let s = #"Hello
world"
printfn "%i" s.Length
0
outputs 12 similarly to equivalent C# code.
What differs is, in fact, the treatment of multi-line string literals by FSI: sending lines 3-5 of the above snippet from VS to FSI with Alt+Enter produces output 11, one less for absence of carriage return within the parsed string literal.
Came out this is a known problem, although I didn't manage to google the rationale behind this behavior.
I ran your code from the fsi and it entered the newline.
let hw = #"hello
world";;
printf "%s" hw;;
output
hello
world

A short cut for "Printf.fprintf"

As I use a lot Printf.fprintf stdout ... in my programs, I would like to rename it by a shorter function. So I write:
let p = Printf.fprintf stdout
And I would hope p "%s" "string" works. However, the compilation gives an error:
File "lib/utility.ml", line 27, characters 8-29:
Error: The type of this expression, ('_a, out_channel, unit) format -> '_a,
contains type variables that cannot be generalized
Does anyone have an idea to rename it so that the application could be as simple as possible?
I think it will work if you eta-expand your definition:
let p fmt = Printf.fprintf stdout fmt

Compilation error complaining about value not being a function

I am trying to experiment in F# for one of the utility tools we need, wherein we want to trawl through a folder of xml files and look for a particular tag. If found then insert another similar tag alongwith it. Finally, output all the filenames for which such additional tags have been inserted. But am getting a compilation error, of which I am not able to make a lot of sense.
let configFile =
Directory.GetFiles(Path.Combine("rootdir", "relativepath"), #"*.xml")
|> Seq.map(fun configFileName ->
let xmlNavigator = XPathDocument(configFileName).CreateNavigator()
let node = xmlNavigator.SelectSingleNode(#"Product/ABc[#type='xyz']")
match node with
| null -> "not configuration present"
| _ ->
let nodeAppender() = node.InsertAfter("<Risk type=""abc1"" methodology=""xyz1""/>")
let parentNode = node.SelectAncestors(XPathNodeType.Root, false)
parentNode.Current.OuterXml)
|> Seq.iter (printfn "%s")
The compilation error is as below:
This value is not a function and cannot be applied
Your string is escaped improperly. It should be:
node.InsertAfter("<Risk type=\"abc1\" methodology=\"xyz1\"/>")
EDIT: Apparently I was typing this as Brian posted his answer. Either escaping each quote char or prefixing with # as-is will work.
It would help to point out what line/column the error location is at.
At a glance, in nodeAppender, it looks like you left off the # on the string literal, which means it is five strings in a row (rather than one string with escaped quotes), which may be the cause of the error.

F# string.Format

I am writing my first F# library
I am trying to use string.Format and it complains that no such function exists.
Is it not available or am I doing something wrong?
If you want to avoid using the full name, you can use open in F#:
open System
let s = String.Format("Hello {0}", "world")
This should work in both F# interactive (enter the open clause first) and in normal compiled applications. The key thing is that you must write String with upper-case S. This is because string in C# isn't a usual type name - it is a keyword refering to the System.String type.
Alternatively, you could also take a look at the sprintf function. It is an F#-specific alternative to String.Format which has some nice benefits - for example it is type checked:
let s = sprintf "Hello %s! Number is %d" "world" 42
The compiler will check that the parameters (string and int) match the format specifiers (%s for string and %d for integers). The function also works better in scenarios where you want to use partial function application:
let nums = [ 1 .. 10 ]
let formatted = nums |> List.map (sprintf "number %d")
This will produce a list of strings containing "number 1", "number 2" etc... If you wanted to do this using String.Format, you'd have to explicitly write a lambda function.
the full name of it is:
System.String.Format

Resources