I am having difficulties escaping '\' in sprintf statements when working with atom editor on Linux with mono.
On Windows with VS:
sprintf "%s" "\\"
is evaluated to
val it : string = "\"
as it should.
If I evaluate the same expression with VSCode or atom-editor under Linux I get
val it : string = "\\"
Further Remark:
If on Windows (I installed Mono on Windows to check this out) I start 'fsharpi' from the 'Mono Command Prompt' the said expression is evaluated correctly as "\". As it does when I do the same thing under Linux.
This looks more like an editor display issue than like a bug in the evaluation itself. To be fair, this always confuses me - should the editor display the string value as it is, or should it display it as a valid escaped F# string? I think both would make sense...
The easiest way to check what value you're really getting is to run a few checks in F# Interactive:
> let s = "\\";;
val s : string = "\"
> s.Length;;
val it : int = 1
> s.[0] = '\\';;
val it : bool = true
Related
We are writing a compiler in OCaml for our own domain specific language. So far, we have working scanner, parser and ast.
What is the best way to test scanner/parser at this point? I know it is possible to pass a sequence of tokens to the parser/scanner and see if it gets accepted/rejected by the scanner/parser. (such as, echo "FLOAT ID" | menhir --interpret --interpret-show-cst parser.mly).
But, is there a way to pass the actual program written in our own language to the scanner/parser and see whether it gets accepted?
I have to add that I am very new to OCaml and I know very little about compilers.
If what you want to do is to give a string to your parser and see if it works, you could do this (supposing your starting point in the parser is prog)
main.ml :
let () =
(* Taking the string given as a parameter or the program *)
let lb = Lexing.from_string Sys.argv.(1) in
(* if you want to parse a file you should write :
let ci = open_in filename in
let lb = Lexing.from_channel ci in
*)
try
let p = Parser.prog Lexer.token lb in
Printf.printf "OK\n"
with _ -> Printf.printf "Not OK\n"
Did I help ? ;-)
This is probably a rather trivial question for the Erlang experts - I'm trying to have my ejabberd server store offline messages (in a Riak db) which inherently do contain double quotes (") around various values, etc. I get a format error when I try to create a Riak database object from them, and testing of replacing the double quotes with an escape character (\") corrects the issue. The question is how can I do this replacement manually?
I tried the following code but somehow doesn't work.
(ejabberd#xxx-xx-xx-xxx)4> re:replace(""hello"", """, "\"", [{return, list}, global]).
* 1: syntax error before: hello
So essentially I'm trying to replace the embedded " around the hello word with \".
I don't know Erlang, but you probably need something like this:
"\"hello\"", "\"", "\\\""
You must escape both " and \ in replacement string.
The Erlang literal syntax for strings uses the "\" (backslash)
character as an escape code. You need to escape backslashes in literal
strings, both in your code and in the shell, with an additional
backslash, i.e.: "\".
Example:
Let's make an example. I use $ Erlang symbol which will be substituted with ascii integer of a character to show what is happening behind each string which basically is a list of integer.
Subject = [$"] ++ "hello" ++ [$"] = "\"hello\"".
Target = [$"] = "\"".
Replacement = [$\\, $\\, $"] = "\\\\\"".
Result = re:replace(Subject, Target, Replacement, [{return, list}, global]).
Now with getting the length of Subject and Result we can find the difference:
7 = length(Subject). %% => 7 characters: " h e l l o "
9 = length(Result). %% => 9 characters: \ " h e l l o \ "
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
I have another question for regular expression in F#:
let tagName = "div"
let ptnTagNotClose = "<" + tagName + "(>|\s+[^>]*>)[^<]"
I want to find the matches for not closing tag in HTML file. The pattern string works in VB.NET.
But for F#, when I debug the above code, I can see the value for ptnTagNotClose:
ptnTagNotClose "<div(>|\\s+[^>]*>)[^<]"
F# automatically change "\s+" to "\\s+", but for regular expression, "\s+" and "\\s+" are different, the results are also different.
Please let me know what to do to avoid F# automatically change the string pattern.
Verbatim string literal could be one solution, but since the tagName can change, i.e. let tagName = "br", then how I can apply verbatim string literal in this case?
Thanks!
John
I don't think that the debug output means what you think it does; using a verbatim string (like "<" + tagName + #"(>|\s+[^>]*>)[^<]") will give you the exact same result because \s isn't a valid escape sequence, so F# interprets the backslash as a literal backslash rather than an escape character.
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