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
Related
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
In Visual Studio 2015:
let myFunction (``string`` : string) =
"\"Quoted string\"" |> (Regex "\"[^\"]*\"").Match |> string
let myOtherFunction (str : string) =
"\"Quoted string\"" |> (Regex "\"[^\"]*\"").Match |> string
First function generates a compiler error, the string function is underlined in red. ("This expression was expected to have type Match -> 'a but here has type string")
Second function is fine, no problems.
Is this by design?
The reason is, your parameter and the call at the end are the same thing. Double backticks are used to escape the name, they are not part of the name.
So in your case that means that ``string`` and string are exactly the same thing, you are trying to pipe into your string parameter. And yes, this is totally by design.
The C# equivalent are #-escaped names, where for example #hello and hello would clash.
We have this small helper functions
open System
let (|NonEmptyString|) value =
if String.IsNullOrEmpty value
then failwith "String must be non-empty."
else value
let (|StartsWithX|) (value:string) =
if value.StartsWith("X") |> not
then failwith "String must start with X."
else value
And using the active pattern matching function NonEmptyString in the function interface works fine:
let hi (NonEmptyString s) = printfn "Hi %s" s
hi "X" // Hi X
hi "" // System.Exception: String must be non-empty.
Now to the problem.
It would be nice to combine some validators together as a more complex validation constraint, like so
let hi (NonEmptyString s & StartsWithX s) = printfn "Hi %s" s
// error FS0038: 's' is bound twice in this pattern
If only one 's' is allowed, we can think of combining the functions so we have only one argument s.
And because active pattern matching functions are functions of course, applying the function composition operator >> but it does not fit here.
let hi (NonEmptyString >> StartsWithX s) = printfn "Hi %s" s
// error FS0010: Unexpected infix operator in pattern
The question is, how can we do that (in F# 4.0) ?
As #kvb commented, the wildcard _ helps in the AND case
// AND
let hi (NonEmptyString _ & StartsWithX s) = printfn "Hi %s" s
The OR case works with with two 's' bindings
// OR
let hi (NonEmptyString s | StartsWithX s) = printfn "Hi %s" s
// The logic here makes less sense. It's kept simple with the given helper functions from above.
Note:
This is just for experimenting with composition of Active Pattern Matching as code contracts in a descriptive way at the function interface.
This can be seen as use or misuse of Active Pattern Matching (idiomatic F# or not), it's your choice!
I am trying to find out how to print out the value of a bigint or System.Numerics.BigInteger in F#. I have found a site here that attempts to explain how to do this, but in the Visual Studio editor, it is flagged as an error. So far, I am just trying something simple like:
printfn "bigInt: %A " 123456789I
But that gets flagged as:
Why does this not work? How can I print out a bigint?
Code:
[<EntryPoint>]
let main =
printfn "bigInt: %A " 123456789I
If you are using an explicit entry point, main needs to accept a single string[] argument and return int. Your sample code is missing both of those requirements. Your printfn line is fine.
[<EntryPoint>]
let main (argv : string[]) =
printfn "bigint %A" 12345I
0
This is not working...
I get error FS0001: The type 'string' is not compatible with the type 'seq'
for the last line. Why?
let rec Parse (charlist) =
match charlist with
| head :: tail -> printf "%s " head
Parse tail
| [] -> None
Parse (Seq.toList "this is a sentence.") |> ignore
The problem is that printf "%s " head means that head must be a string, but you actually want it to be a char, so you'll see that Parse has inferred type string list -> 'a option. Therefore, F# expects Seq.toList to be applied to a string seq, not a string.
The simple fix is to change the line doing the printing to printf "%c " head.