Does F# have its own string manipulation libraries? - dll

Does F# have its own string manipulation libraries?
As I am attempting to learn F#, I find myself using the existing System.string methods?
Should I be doing this?
Code:
open System
type PhoneNumber =
{ CountryCode:int
Number:string }
// b. Create a function formatPhone that accepts a PhoneNumber record and formats it to look like something like this: "+44 1234 456789"
let formatPhone phoneNumber =
let getLeadingCharacters (length:int) (text:string) =
text.Substring(0, length)
let getLastCharacters (length:int) (text:string) =
text.Substring(text.Length - length, length)
printf "+%i %s %s" phoneNumber.CountryCode
(phoneNumber.Number |> getLeadingCharacters 4)
(phoneNumber.Number |> getLastCharacters 6)
formatPhone { CountryCode=44; Number="123456789" };;
UPDATE
Updated function from:
let formatPhone phoneNumber =
let getLeadingCharacters (length:int) (text:string) =
text.Substring(0, length)
let getLastCharacters (length:int) (text:string) =
text.Substring(text.Length - length, length)
printf "+%i %s %s" phoneNumber.CountryCode
(phoneNumber.Number |> getLeadingCharacters 4)
(phoneNumber.Number |> getLastCharacters 6)
formatPhone { CountryCode=44; Number="123456789" };;
to:
let formatPhone phoneNumber =
printf "+%i %s %s" phoneNumber.CountryCode
phoneNumber.Number.[0..3]
phoneNumber.Number.[4..8]
formatPhone { CountryCode=44; Number="123456789" };;

No, F# does not have a specific String library that duplicates the .NET library. It does have a string module with extra string functions.
Yes, use the .NET functions.
The fact that F# can make use of all of the .NET library is one of it's strongest features. It does seem odd at first to mix functions using curried parameters with functions from .NET using tuple parameters.
That is why in NuGet you will see packages that also have the FSharp extension. e.g. MathNet Numerics and MathNet Numerics FSharp. These are wrapper functions that allow for idiomatic F# use of the .NET library.
In checking the F# documentation for Strings there is one section noting the String class and another section noting String module.
Part of original answer that is no longer correct.
When looking for functions and methods for use with F# I often use this trick.
To search .NET use class as a keyword and to search for F# specific code use module as keyword.
For example:
Google: MSDN string class
First item: String Class
Google: MSDN string module
First item: Core.String Module (F#) (This is now a 404) but it is also a valid link for F# Language Reference for String. Something is amiss.

It depends.
If you are using open source libraries like FAKE for scripting,
you can reuse it's StringHelper module.
FAKE contains a StringHelper module https://github.com/fsharp/FAKE/blob/master/src/app/FakeLib/StringHelper.fs

Related

Server side validation library for Kotlin

Can anyone please suggest me good server side validation library for kotlin.
Which can perform basic validation like below
Checking for spaces and new line in a string
Checking the minimum and maximum of character in a string
Checking empty string
As I need to use a validation library instead of below code
val data.name = "test test"
val nameMaxLimit: Int = 256
if (data.name.contains(" ") || data.name.isNullOrEmpty() || data.name.length > nameMaxLimit) {
return true
}
My project is a Gradle Project, So gradle supported validation library will be blessed
You can use beans validation. I think it is the best way.
You would need to annotate each field with the rules you want.
Then you would tell the validations to run.
It would return to you an array of violations.
Here an example:
import javax.validation.Validator
val violations = validator.validate(data)
if (violations.isEmpty()) {
successAction()
}

f# - how to serialize option and DU as value or null (preferably with json.net)

How can i get my json from web api to format only value or null for Option types and Discriminated Unions preferably using Newtonsoft.
I am currently using Newtonsoft and only have to add this to web api for it to work:
config.Formatters.JsonFormatter.SerializerSettings <- new JsonSerializerSettings()
When i consume the data on my side, i can easily convert it back to an F# item using: JsonConvert.DeserializeObject<'a>(json)
The api will be consumed by NON .NET clients as well so i would like a more standard formatted json result.
I would like to to fix my issue, w/o having to add code or decorators to all of my records/DU in order for it to work. I have lots of records with lots of properties, some are Option.
ex (this is how DU is serializing):
// When value
"animal": {
"case": "Dog"
}
// When no value
"animal": null
This is what I need:
// When value
"animal": "Dog"
// When no value
"animal": null
This is how an Option type is serializing:
"DocumentInfo": {
"case": "Some",
"fields": [
{
"docId": "77fb9dd0-bfbe-42e0-9d29-d5b1f5f0a9f7",
"docType": "Monkey Business",
"docName": "mb.doc",
"docContent": "why cant it just give me the values?"
}
]
}
This is what I need:
"DocumentInfo": {
"docId": "77fb9dd0-bfbe-42e0-9d29-d5b1f5f0a9f7",
"docType": "Monkey Business",
"docName": "mb.doc",
"docContent": "why cant it just give me the values?"
}
Thank you :-)
You could try using Chiron. I haven't used it myself so I can't give you an extensive example, but https://neoeinstein.github.io/blog/2015/12-13-chiron-json-ducks-monads/index.html has some bits of sample code. (And see https://neoeinstein.github.io/blog/2016/04-02-chiron-computation-expressions/index.html as well for some nicer syntax). Basically, Chiron knows how to serialize and deserialize the basic F# types (strings, numbers, options, etc.) already, and you can teach it to serialize any other type by providing that type with two static methods, ToJson and FromJson:
static member ToJson (x:DocumentInfo) = json {
do! Json.write "docId" x.docId
do! Json.write "docType" x.docType
do! Json.write "docName" x.docName
do! Json.write "docContent" x.docContent
}
static member FromJson (_:DocumentInfo) = json {
let! i = Json.read "docId"
let! t = Json.read "docType"
let! n = Json.read "docName"
let! c = Json.read "docContent"
return { docId = i; docType = t; docName = n; docContent = c }
}
By providing those two static methods on your DocumentInfo type, Chiron will automatically know how to serialize a DocumentInfo option. At least, that's my understanding -- but the Chiron documentation is sadly lacking (by which I mean literally lacking: it hasn't been written yet), so I haven't really used it myself. So this may or may not be the answer you need, but hopefully it'll be of some help to you even if you don't end up using it.
I have found the solution that allows me to use Newtonsoft (JSON.NET), apply custom converters for my types where needed and not require any changes to my DU's or Records.
The short answer is, create a custom converter for Json.Net and use the Read/Write Json overrides:
type CustomDuConverter() =
inherit JsonConverter() (...)
Unfortunately the ones I have found online that were already created doesn't work as is for my needs listed above, but will with slight modification. A great example is to look at: https://gist.github.com/isaacabraham/ba679f285bfd15d2f53e
To apply your custom serializer in Web Api for every call, use:
config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new CustomDuConverter())
To deserialize use (example that will deserialize to DU):
JsonConvert.DeserializeObject<Animal>("Dog", customConverter)
ex:
type Animal = Dog | Cat
json:
"animal": "Dog"
This will allow you to create a clean Api for consumers and allow you to consume 3rd party Json data into your types that use Option, etc.

String with variable inside that can dynamically change

I'm trying to setup an API in golang, for specific needs, I want to be able to have an environment variable that would contain an URL as string (i.e : "https://subdomain.api.com/version/query") and I want to be able to modify the bold parts within an API call.
I have no clue on how I could achieve this.
Thanks for your time,
Paul
There are many ways, one which allows the URL to be configured from the environment, then to have the url configured dynamically at runtime, would be to use a template.
You could expect a template from the ENV:
apiUrlFromEnv := "https://{{.Subdomin}}.api.com/{{.Version}}/query" // get from env
Modified From the docs:
type API struct {
Subdomain string
Version string
}
api := API{"testapi", "1.1"}
tmpl, err := template.New("api").Parse(apiUrlFromEnv)
if err != nil { panic(err) }
err = tmpl.Execute(os.Stdout, api) // write to buffer so you can get a string?
if err != nil { panic(err) }
The simplest way is to use fmt.Sprintf.
fmt.Sprintf(format string, a ...interface{}) string
As you see this function returns a new formatted string and this is built-in library. Furthermore you can use indexing to place arguments in a template:
In Printf, Sprintf, and Fprintf, the default behavior is for each formatting verb to format successive arguments passed in the call. However, the notation [n] immediately before the verb indicates that the nth one-indexed argument is to be formatted instead.
fmt.Sprintf("%[2]d %[1]d %d[2]\n", 11, 22)
But if you want to use named variables you should use text/template package.

How to add subscripts to my custom Class in Perl 6?

I am new to Perl 6. I have the following code in my Atom Editor, but I still don't understand how this works. I copied the following code, as the docs.raku.org said, but it seems that it does not work. So I changed the code to this:
use v6;
class HTTPHeader { ... }
class HTTPHeader does Associative {
has %!fields handles <self.AT-KEY self.EXISTS-KEY self.DELETE-KEY self.push
list kv keys values>;
method Str { say self.hash.fmt; }
multi method EXISTS-KEY ($key) { %!fields{normalize-key $key}:exists }
multi method DELETE-KEY ($key) { %!fields{normalize-key $key}:delete }
multi method push (*#_) { %!fields.push: #_ }
sub normalize-key ($key) { $key.subst(/\w+/, *.tc, :g) }
method AT-KEY (::?CLASS:D: $key) is rw {
my $element := %!fields{normalize-key $key};
Proxy.new(
FETCH => method () { $element },
STORE => method ($value) {
$element = do given $value».split(/',' \s+/).flat {
when 1 { .[0] } # a single value is stored as a string
default { .Array } # multiple values are stored as an array
}
}
);
}
}
my $header = HTTPHeader.new;
say $header.WHAT; #-> (HTTPHeader)
"".say;
$header<Accept> = "text/plain";
$header{'Accept-' X~ <Charset Encoding Language>} = <utf-8 gzip en>;
$header.push('Accept-Language' => "fr"); # like .push on a Hash
say $header.hash.fmt;
"".say;
say $header<Accept-Language>.values;
say $header<Accept-Charset>;
the output is:
(HTTPHeader)
Accept text/plain
Accept-Charset utf-8
Accept-Encoding gzip
Accept-Language en fr
(en fr)
utf-8
I konw it works, but the document in docs.raku.org is a little different to this, which doesn't have "self" before the AT-KEY method in the 7th line. Is there any examples that more detail about this?
Is there any examples that more detail about this?
Stack overflow is not really the place to request more detail on a published example. This is the perl6 doco on the community itself - I would suggest that the most appropriate place if you have further queries is the Perl6 users mailing list or, failing that, the IRC channel, perhaps.
Now that you've posted it though, I'm hesitant to let the question go unaddressed so, here are a couple of things to consider;
Firstly - the example you raised is about implementing associative subscripting on a custom (ie user defined) class - it's not typical territory for a self-described newbie. I think you would be better off looking at and implementing the examples at Perl6 intro by Naoum Hankache whose site has been very well received.
Option 1 - Easy implementation via delegation
Secondly, it's critical to understand that the example is showing three options for implementing associative subscripting; the first and simplest uses delegation to a private hash attribute. Perl6 implements associative and positional subscripts (for built-in types) by calling well-defined methods on the object implementing the collection type. By adding the handles trait on the end of the definition of the %!fields attribute, you're simply passing on these method calls to %!fields which - being a hash - will know how to handle them.
Option 2 - Flexible keys
To quote the example:
However, HTTP header field names are supposed to be case-insensitive (and preferred in camel-case). We can accommodate this by taking the *-KEY and push methods out of the handles list, and implementing them separately...
Delegating all key-handling methods to the internal hash means you get hash-like interpretation of your keys - meaning they will be case-sensitive as hash keys are case-sensitive. To avoid that, you take all key-related methods out of the handles clause and implement them yourself. In the example, keys are ran through the "normalizer" before being used as indexes into %!fields making them case-insensitive.
Option 3 - Flexible values
The final part of the example shows how you can control the interpretation of values as they go into the hash-like container. Up to this point, values supplied by assigning to an instance of this custom container had to either be a string or an array of strings. The extra control is achieved by removing the AT_KEY method defined in option 2 and replacing it with a method that supplies a Proxy Object. The proxy object's STORE method will be called if you're assigning to the container and that method scans the supplied string value(s) for ", " (note: the space is compolsory) and if found, will accept the string value as a specification of several string values. At least, that's what I think it does.
So, the example has a lot more packed into it than it looks. You ran into trouble - as Brad pointed out in the comments - because you sort-of mashed option 1 togeather with option 3 when you coppied the example.

Is it possible to pass a variable's name along with the value, when passing through functions?

I want to know if it's possible to retrieve the variables name from when it was passed into a certain function. For example, if I call parseId(myId) to a function with the signature parseId(id), i can obviously retrieve the value of 'id'. However, is there any way I can retrieve 'myId' as a string (without passing it as another value)?
Specifically in vb.net, but I'm interested in how it would work in any given language.
This is all just random thoughts.. feel free to dismiss or not ;-p
Re your comment about use with stored procedures... if you want to go that route, I wouldn't mess around with the local variable names; that is an implementation detail. However, you could expose those details on an interface method and use the names from there, since that is more formalised - for example (C#):
interface ICustomerRepository {
Customer GetById(int id); // perhaps an attribute to name the sproc
}
You can use similar expression-tree parsing (as discussed here) to get the name and value of the parameter, for example:
var repoWrapper = new Repo<ICustomerRepository>();
int custId = 12345;
var cust = repoWrapper.Execute(r => r.GetById(custId));
Here we'd want to resolve the argument to GetById as "id" (not "custId"), with value 12345. This is actually exactly what my protobuf-net RPC code does ;-p (just don't ask me to translate it to VB - it is hard enough to write it in a language you know well...)
No, you can't do that in the normal sense. What are you really trying to accomplish with this?
You can do this in .NET 3.5 and above using expression trees; I'll knock up a C# example, and try to run it through reflector for VB...
C#:
static void Main()
{
int i = 17;
WriteLine(() => i);
}
static void WriteLine<T>(Expression<Func<T>> expression)
{
string name;
switch (expression.Body.NodeType)
{
case ExpressionType.MemberAccess:
name = ((MemberExpression)expression.Body).Member.Name;
break;
default:
throw new NotSupportedException("Give me a chance!");
}
T val = expression.Compile()();
Console.WriteLine(name + "=" + val);
}
The VB is below, but note that the VB compiler seems to use different names (like $VB$Local_i, not i):
Sub Main()
Dim i As Integer = 17
WriteLine(Function() i)
End Sub
Private Sub WriteLine(Of T)(ByVal expression As Expression(Of Func(Of T)))
If (expression.Body.NodeType <> ExpressionType.MemberAccess) Then
Throw New NotSupportedException("Give me a chance!")
End If
Console.WriteLine((DirectCast(expression.Body, MemberExpression).Member.Name
& "=" & Convert.ToString(expression.Compile.Invoke)))
End Sub