In the docs: https://bucklescript.github.io/docs/en/object.html there are examples for a record with mutable fields and optional fields. When I try to use both it fails:
Compiles:
type person = {
mutable age: int;
job: string;
} [##bs.deriving abstract]
let joe = person ~age:20 ~job:"teacher"
let () = ageSet joe 21
Adding the [#bs.optional] attribute:
type person = {
mutable age: int;
job: string [#bs.optional];
} [##bs.deriving abstract]
let joe = person ~age:20 ~job:"teacher"
let () = ageSet joe 21
Error message:
Line 7, 20:
This expression has type unit -> person
but an expression was expected of type person
Line 7 is the ageSet line.
Am I missing anything here?
I re-read the documentation and this is the part I missed
Note: now that your creation function contains optional fields, we mandate an unlabeled () at the end to indicate that you've finished applying the function.
type person = {
mutable age: int;
job: string [#bs.optional];
} [##bs.deriving abstract]
let joe = person ~age:20 ~job:"teacher" ()
let () = ageSet joe 21
Related
This question already has an answer here:
Return &str instead of std::borrow::Cow<'_, str>
(1 answer)
Closed 8 months ago.
I am trying to create a function that takes a &str as an input and gives a &str as an output. However I do not find any solution on how to comply with the borrow checker rules. It seems that the returned type is Cow, but I didn't found a way to convert it to a &str. Maybe I should keep this type?
Here is the function that I want to write:
fn replace_by_regex<'a>(text: &'a str) -> &'a str {
let re = Regex::new(r"(PATTERN)").unwrap();
let after = re.replace_all(&text, "").to_string().as_str();
// println!("{}", after);
after
}
But I get this error:
error[E0515]: cannot return value referencing temporary value
--> src/lib.rs:91:5
|
89 | let after = re.replace_all(&text, "").to_string().as_str();
| ------------------------------------- temporary value created here
90 | // println!("{}", after);
91 | after
| ^^^^^ returns a value referencing data owned by the current function
But at the end of the day I aim to collect a modified &str.
How about returning a String instead? Got it working in the playground and included a test.
use regex::Regex;
pub fn replace_by_regex(text: &str) -> String {
let re = Regex::new(r"(PATTERN)").unwrap();
let after = re.replace_all(text, "");
println!("{}", after);
after.into_owned()
}
In F#, assume I have a person record as:
type person =
{ LastName: string option
BirthDate: System.DateTime option }
Now, I want to create a list of 100 persons (this fails. Both name and The System.DateTime(...) is incorrect):
let people = [for a in 1 .. 100
do yield {
LastName= Some "LastName"+a
BirthDate = System.DateTime(2012,11,27)
}]
How is this done?
TIA
There are two separate issues with the code, but your general approach is good!
First, Some "LastName"+a is interpereted as (Some "LastName")+a, which is not the right parenthesization. Also a is an int which cannot be automatically turned into a string, so you need to explicitly convert it. The correct version is Some("LastName" + string a).
Second, System.DateTime(2012,11,27) is DateTime, but you need an option. You can fix this just by adding Some and the right parentheses, i.e. Some(System.DateTime(2012,11,27)).
As a bonus, you can reduce do yield to -> (this is just a syntactic sugar to make this kind of thing shorter). I would write:
open System
let people =
[ for a in 1 .. 100 ->
{ LastName= Some ("LastName"+string a)
BirthDate = Some(DateTime(2012,11,27)) } ]
I am using a web service to get information. When said info is returned, I convert the data received from jason to a dict.
When Dumping dict object, some of the items arrive like this:
▿ (2 elements)
- key: "street1"
- value: <null> #4
How would i go about reading this data and knowing that the value is NULL
I have tried the following:
let street1:String = dict?["street1"] as! String
This fails with: Could not cast value of type 'NSNull' (0x10fbf7918) to 'NSString' (0x10f202c60).
The data could have a String value. So I tried:
let street1:Any = dict?["street1"] as Any
When I print street1 thus
street1: Optional()
I get the following
street1: Optional()
So my question is:
How would i go about reading this data and knowing that the value is null.
You can use if let for this type of nil check.
Try this instead:
if let street1 = dict?["street1"] as? String {
// If this succeeds then you can use street1 in here
print(street1)
}
Update:
var t_street1 = ""
if let street1 = dict?["street1"] as? String {
t_street1 = street1
}
No need for the else t_street1 is automatically empty since you assign it empty.
I'm doing my first dive into F# at work, and I'm moving several C# unit tests I have to F# as an exercise. Our tests are quite complex, but I relish the challenge (With setups, inheritance, teardowns and so on).
As I've been seeing, mutability should be avoided if possible, but when writing the [SetUp] parts of the tests I can't seem to find a way to jump over mutability. Example that creates a dummy XML for a test::
[<TestFixture>]
type CaseRuleFixture() =
[<DefaultValue>] val mutable xsl : XNamespace
[<DefaultValue>] val mutable simpleStylesheet : XElement
[<DefaultValue>] val mutable testNode : XElement
[<DefaultValue>] val mutable rootNode : XElement
[<DefaultValue>] val mutable root : XElement
let CreateXsltHeader(xsl: XNamespace) =
// Build XSLT header
let styleSheetRoot =
new XElement(
xsl + "stylesheet",
new XAttribute(XName.Get "version", "1.0"),
new XAttribute(XNamespace.Xmlns + "xsl", "http://www.w3.org/1999/XSL/Transform"),
new XAttribute(XNamespace.Xmlns + "msxsl", "urn:schemas-microsoft-com:xslt"),
new XAttribute(XName.Get "exclude-result-prefixes", "msxsl"),
new XAttribute(XNamespace.Xmlns + "utils", "urn:myExtension"))
let outputNode =
new XElement(
xsl + "output",
new XAttribute(XName.Get "method", "xml"),
new XAttribute(XName.Get "indent", "yes"))
styleSheetRoot.Add outputNode
styleSheetRoot
[<SetUp>]
member this.SetUp() =
this.xsl <- XNamespace.Get "http://www.w3.org/1999/XSL/Transform"
this.simpleStylesheet <- CreateXsltHeader(this.xsl)
Directory.EnumerateFiles "Templates"
|> Seq.iter(fun filepath -> this.simpleStylesheet.Add(XElement.Parse(File.ReadAllText filepath).Elements()))
let variable =
new XElement(
this.xsl + "variable",
new XAttribute(XName.Get "name", "ROOT"),
new XAttribute(XName.Get "select", "ROOT"))
this.simpleStylesheet.Add(variable)
let rootTemplate = new XElement(this.xsl + "template", new XAttribute(XName.Get "match", "/ROOT"))
this.simpleStylesheet.Add(rootTemplate);
this.rootNode <- new XElement(XName.Get "ROOT")
rootTemplate.Add(this.rootNode);
this.root <- new XElement(XName.Get "ROOT")
this.testNode <- new XElement(XName.Get "TESTVALUE")
this.root.Add(this.testNode)
[<Test>]
member this.CaseCapitalizeEachWordTest() =
this.testNode.Value <- " text to replace ";
let replaceRule = new CaseRule();
replaceRule.Arguments <- [| "INITIALS" |];
this.rootNode.Add(
replaceRule.ApplyRule [| new XElement(this.xsl + "value-of", new XAttribute(XName.Get "select", "TESTVALUE")) |]);
let parser = new XsltParserHelper(this.simpleStylesheet);
let result = parser.ParseXslt(this.root);
let value = result.DescendantsAndSelf() |> Seq.find(fun x -> x.Name = XName.Get "ROOT")
Assert.AreEqual(" Text To Replace ", value.Value)
Those [<DefaultValue>] val mutable to declare the variables (without initializing because that's SetUp job) and make those variables available to all the class scope, and the fact that I've basically done a 1:1 translation from what I had in C# without any apparent gaining in syntax and readability gave me the chills. Is there any way to rewrite these kind of tests and setups that looks nicer? Because all examples I've seen all over internet are simple, small and do not cover these cases.
Let's reduce the problem to a more manageable size first:
Reduced problem
In this test, you have two mutable fields being initialized in the SetUp method:
[<TestFixture>]
type MutableTests() =
[<DefaultValue>] val mutable foo : int
[<DefaultValue>] val mutable bar : int
[<SetUp>]
member this.SetUp () =
this.foo <- 42
this.bar <- 1337
[<Test>]
member this.TheTest () =
Assert.AreEqual(42, this.foo)
Assert.AreEqual(1337, this.bar)
Obviously, this is a stand-in for the real problem.
Functions that return values
Instead of setting class fields, why not write functions that initialize the values that you need?
module BetterTests =
let createDefaultFoo () = 42
let createDefaultBar () = 1337
[<Test>]
let ``a test using individual creation functions`` () =
let foo = createDefaultFoo ()
let bar = createDefaultBar ()
Assert.AreEqual(42, foo)
Assert.AreEqual(1337, bar)
If you wan't all the values at once (like you have access to all fields from within a class), you can define a single function that returns all values in a tuple or record:
let createAllDefaultValues () = createDefaultFoo (), createDefaultBar ()
[<Test>]
let ``a test using a single creation function`` () =
let foo, bar = createAllDefaultValues ()
Assert.AreEqual(42, foo)
Assert.AreEqual(1337, bar)
This example uses an int * int tuple, but it might be more readable to define a record:
type TestValues = { Foo : int; Bar : int }
let createDefaultTestValues () = {
Foo = createDefaultFoo ()
Bar = createDefaultBar () }
[<Test>]
let ``a test using a single creation function that returns a record`` () =
let defaultValues = createDefaultTestValues ()
Assert.AreEqual(42, defaultValues.Foo)
Assert.AreEqual(1337, defaultValues.Bar)
Notice that, unlike classes in C#, records in F# are super-lightweight to declare.
If you want to learn more about idiomatic unit testing with F#, a good place to start could be my Pluralsight course about unit testing with F#.
Please see I want list employee objects. So I have below two options.
List<Tuple<int, string, string, string>>
List<Employee>where Employee is class contains 4 properties.
My doubt is what should I use(tuple or list of employee object?
If it is List<Employee> then in which scenario I should use List<Tuple<int, string, ...>>.
You should not use tuples unless you are doing some sort of arithmetic operation where tuple would be an acceptable and widely understood method of supplying values. Tuples make it a maintenance nightmare for anyone who is not familiar with your process as you built it.
Edit: Think about the difference between seeing:
var employeeList = DAL.getEmployees();
var activeEmployees = employeeList.Where(employee => employee.IsActive);
vs
var employeeTuple = DAL.getEmployees();
var activeEmployees = employeeTuple.Where(employee => employee.Item3);
In the second example, I know THAT you created an active employee list, but I don't know HOW you did it.
That's rather obvious. If you already have the Employee class then using List<Employee> is straightforward:
List<Employee> list = new List<Employee>();
list.Add( e );
...
Employee e = list.Where( i => i.Name == "John" ).FirstOrDefault();
whereas using List<Tuple<...>> is at least cumbersome:
List<Tuple<....>> list = new List<Tuple<....>>();
list.Add( new Tuple<...>( e.Name, e.Surname, e.Whateverelse, e.YetAnother ) );
...
// retrieve the tuple
var tuple = list.Where( i => i.Item1 == "John" );
// make Employee out of it
Employee e = new Employee( e.Item1, e.Item2, e.Item3, e.Item4 );