I have a code snippet here but i don't understand the use of "new (code)" in it.
type Product (code:string, price:float) =
let isFree = price=0.0
new (code) = Product(code,0.0)
member this.Code = code
member this.IsFree = isFree
Specifically why the need to enclose the "code" variable inside brackets.
That's a constructor. From MSDN: Classes (F#) (see section 'Constructors'):
You can add additional constructors by using the new keyword to add a member, as follows:
new (argument-list) = constructor-body
In your example, the Product type has one default constructor which accepts code and price, and one additional constructor that takes only code and applies the default constructor with 0.0 for price. In this case, the parentheses around code are not strictly required, and the code would compile just the same without it, although it would be required if you want constructor that takes zero parameters or more than one parameter.
The equivalent C# would be something like this:
public class Product
{
private string code;
private bool isFree;
public Product(string code, double price) {
this.code = code;
this.isFree = price == 0.0;
}
public Product(string code) : this(code, 0.0) { }
public string Code { get { return this.code; } }
public float IsFree { get { return this.isFree; } }
}
Related
There is nameof operator in C#, it allows to get property name at compile time:
var name = nameof(User.email);
Console.WriteLine(name);
//Prints: email
It is not possible to use reflection in flutter and I do not want to hardcode names of properties i.e. to be used for querying SQLite tables. Is there any workaround?
***Currently I'm using built_value library.
For the archives, I guess, this isn't possible as Dart doesn't store the names of variables after compiling, and as you mentioned, Flutter doesn't support reflection.
But you can still hardcode responsibly by grouping your properties as part of the object that they belong to, like with JSON:
class User {
final String email;
final String name;
const User({required this.email, required this.name});
Map toJson() => {
"email": email,
"name": name,
};
}
Instead of remembering to type out "email" and "name" whenever you use User, just call User.toJson(). Then, when you want to rename your variables, you can use your IDE's "rename all", or just skim over your User class to quickly change all of the names without missing any.
I'm currently monitoring the progress on the dart:mirrors package, which offers some neat reflective properties and methods, though, I hadn't found a simple way to just get the name of a symbol like nameof() does.
Example:
import 'dart:mirrors';
class User {
final String email;
final String name;
const User({required this.email, required this.name});
}
void main() {
reflectClass(User).declarations.forEach((key, value) {
print(value.simpleName);
});
}
Output:
Symbol("email")
Symbol("name")
Symbol("User")
These are of type Symbol.
More here: https://api.dart.dev/stable/2.4.0/dart-mirrors/dart-mirrors-library.html
So, until they develop a nameof, I've created an extension on symbol:
extension SymbolExtensions on Symbol {
String get nameof =>
RegExp(r'"(.*?)"').firstMatch(toString())!.group(1).toString();
}
So, you could do:
print(reflectClass(User)
.declarations[#email)]!
.simpleName
.nameof);
Output:
email
It's a start. Dart is still growing.
You can use code generation.
The basic idea is to create a nameof annotation class and mark parts of your code with it. You also need to create a code generator that handles your annotated code. Look at the json_serializable package for an example and create your own code generator.
If you do not want to create your own generator, use a ready-made package nameof: https://pub.dev/packages/nameof
Short how-to with this package.
Mark your class with nameof annotation.
#nameof
class Car {
final double price;
final double weigth;
final int year;
final String model;
Car(this.price, this.weigth, this.year, this.model);
Car.sedan(double price, double weigth, int year)
: this(price, weigth, year, 'Sedan');
}
Run the code generator.
flutter pub run build_runner build
Then use the generated class, which will look something like this.
/// Container for names of elements belonging to the [Car] class
abstract class NameofCar {
static const String className = 'Car';
static const String constructor = '';
static const String constructorSedan = 'sedan';
static const String fieldPrice = 'price';
static const String fieldWeigth = 'weigth';
static const String fieldYear = 'year';
static const String fieldModel = 'model';
}
You can implement your own nameOf function:
String? nameOf(dynamic o) {
if (o == null) return "null";
try {
if (o is List) {
var first = o.length > 0 ? o[0] : null;
if (first != null) {
var elementType = nameOf(first)!;
Log.debug("nameOf: List<$elementType>");
if (!isMinified(elementType))
return "List<$elementType>";
}
} else {
Function? getTypeName = o.getTypeName;
if (getTypeName != null) return getTypeName();
}
} catch (e) {
Log.debug("ignored nameOf error: $e, falling back to o.runtimeType: ${o.runtimeType}");
}
return o.runtimeType.toString();
}
bool isMinified(String type) => type.startsWith("minified:");
Here Cycle is a domain class
class Cycle {
int lenght = 42
String[] monitor = new String[length]
static mapping = {
monitor defaultValue:"defaultstrval(length)"
}
def defaultstrval(int length)
{
String[] defaultval =new String[length]
for(int i=0;i<length;i++)
{
defaultval[i]=","
}
return defaultval
}
}
Is Domain class only accept sql function.I really need help with good example.
Rather than using the mapping closure to call your function you can simply call the function from your variable assignment like so
String[] monitor = defaultstravel(length)
I am having difficulty to convert following C# code to F#:
class Foo
{
public Foo() { }
public Foo(string name) { }
}
class Bar : Foo
{
public Bar() : base() { }
public Bar(string name) : base(name) { }
public string Name { get; set; }
}
I first tried following, but it is reporting error
Constructors for the type 'Bar' must directly or indirectly call its
implicit object constructor. Use a call to the implicit object
constructor instead of a record expression.
type Foo() =
new(name:string) = Foo()
type Bar() =
inherit Foo()
new(name:string) = { inherit Foo(name) }
member val Name:string = null with get, set
Then I tried following, but it is now reporting error on the auto property
'member val' definitions are only permitted in types with a primary
constructor. Consider adding arguments to your type definition"
type Foo() =
new(name:string) = Foo()
type Bar =
inherit Foo
new(name:string) = { inherit Foo(name) }
member val Name:string = null with get, set
If you want F# source code who compiles to precisely the same API as given by your C# code, the answer is as follows:
type Foo =
new() = {}
new(name:string) = { }
type Bar =
inherit Foo
[<DefaultValue>]
val mutable private name:string
new() = { inherit Foo() }
new(name) = { inherit Foo(name) }
member x.Name with get() = x.name and set v = x.name <- v
This compiles:
type Foo() =
new(name:string) = Foo()
type Bar(name : string) =
inherit Foo()
new() = Bar(null) // or whatever you want as a default.
member val Name:string = name with get, set
See Constructors (F#) and Inheritance (F#).
Looking at the decompilation, the C# would be (with attributes removed):
public class Bar : Program.Foo {
internal string Name#;
public string Name {
get {
return this.Name#;
}
set {
this.Name# = value;
}
}
public Bar(string name) {
this.Name# = name;
}
public Bar() : this(null) {
}
}
public class Foo {
public Foo() {
}
public Foo(string name) : this() {
}
}
If a class has a parameter list directly after its name (including ()), it has a primary constructor. Using it, any inherit declarations are placed only in this primary constructor, which comes directly after the class declaration and before any member declarations.
It is unclear what you are trying to achieve. The class Foo has a constructor taking a string argument, only to discard it. A (technically) valid, similar pair of classes would be this:
type Foo(name:string) =
member f.NameLength = name.Length
type Bar(initialName) = // WARNING: this will not end well
inherit Foo(initialName)
member val Name:string = initialName with get, set
But this is not sensible code. Foo will keep the initial name even if the name in Bar is changed. Bar.Name.Length returns the current name's length, while Bar.NameLength returns the initial name's length.
To keep the default constructor, one could add new () = Bar(null) (or the equivalent in Foo), but please note that null is considered an interop-only feature. It is not used in F# facing code; if possible, use the appropriate option type or an empty string respectively (depending on whether the string is just empty or doesn't exist at all).
Also, inheriting classes is discouraged in the F# component design guidelines -- for good reason. There are few use cases, but those usually involve a tiny base class and a derived class that is a perfect superset of it. It is far more common to compose types by using one class as a member of another.
I don't know how relevant this is, but here is an example of a class with default constructor and an additional constructor that uses it:
type Text500(text : string) =
do if text.Length > 500 then
invalidArg "text" "Text of this type cannot have a length above 500."
member t.Text = text
new () = Text500("")
This utilizes the primary constructor to verify input and has an additional, parameterless constructor that uses an empty string. (I'm not sure if the additional constructor would be useful in actual applications.)
Is there a built-in / easy way to set mappings between domain class properties and JSON strings that don't have exact matches for the property names?
For example, when I have a domain class:
class Person {
String jobTitle
String favoriteColor
static constraints = {
jobTitle(blank: false)
favoriteColor(blank: false)
}
}
And someone's giving me the following JSON:
{ "currentJob" : "secret agent", "the-color" : "red" }
I'd like to be able to still do this:
new Person(request.JSON).save()
Is there a way in groovy/grails for me to map currentJob -> jobTitle and the-color -> favorite color?
EDIT:
I've done a little experimenting, but I still haven't gotten it working. But I have found out a couple interesting things...
At first I tried overwriting the setProperty method:
#Override
setProperty(String name, Object value) {
if(this.hasProperty(name)) this[name] = value
else {
switch(name) {
'currentJob': this.jobTitle = value; break;
'the-color': this.favoriteColor = value; break;
}
}
}
But this doesn't work for two reasons: 1) setProperty is only called if there is a property that matches name and 2) "this[name] = value" calls setProperty, leading to an infinite recursive loop.
So then I thought, well screw it, I know what the incoming json string looks like (If only I could control it), I'll just get rid of the line that handles the scenario where the names match and I'll override hasProperty, maybe that will work:
#Override
void setProperty(String name, Object value) {
switch(name) {
'currentJob': this.jobTitle = value; break;
'the-color': this.favoriteColor = value; break;
}
}
#Override
boolean hasProperty(String name) {
if(name == "currentJob" || name == "the-color") return true
return false
}
But no, that didn't work either. By a random stroke of luck I discovered, that not only did I have to overwrite hasProperty(), but I also had to have an empty setter for the property.
void setCurrentJob(){ }
That hack worked for currentJob - I guess setProperty only gets called if hasProperty returns true and there is a setter for the property (Even if that setter is auto generated under the covers in grails). Unfortunately I can't make a function "setThe-Color" because of the dash, so this solution doesn't work for me.
Still stuck on this, any help would definitely be appreciated.
EDIT:
Overriding the void propertyMissing(String name, Object value){} method is called by this:
Person person = new Person()
person["currentJob"] = "programmer"
person["the-color"] = "red"
But not by this:
Person person = new Person(["currentJob":"programmer", "the-color":"red"])
Jena's OntModel has a method listHierarchyRootClasses that returns an iterator over the classes in this ontology model that represent the uppermost nodes of the class hierarchy. But why does OntModel have no method of the same function for the semantic properties? There is a property hierarchy as well, so why developers make a listHierarchyRootProperties?
I have solved this by using listAllOntProperties method, but it is a workaround, and does not look good. I don't understand why is it necessary. What is the reason?
Jena is an open-source project. You are more than welcome to submit a patch with the additional functionality you would like to see in the library. Please submit patches via the Jira account.
To answer your direct question: there's no particular reason why there's no equivalent for the property hierarchy. However, property inheritance isn't as widely used as as class inheritance in OWL, and in all the years since I wrote listHierarchyRootClasses, you're the first person I can remember asking about the property hierarchy.
Here is my workaround, which produces alphabetically sorted hierarchy (tree) of semantic properties. The getPropertyTreeModel() method returns a model for an ice:tree component and the parameter domContent is not important (it is for my special needs):
protected static DefaultTreeModel getPropertyTreeModel(OntModel ontModel, Document domContent) {
System.out.println("Creating property model...");
DefaultMutableTreeNode rootTreeNode = getRoot();
DefaultTreeModel treeModel = new DefaultTreeModel(rootTreeNode);
Iterator i = getAlphabeticalIterator(ontModel.listAllOntProperties().filterDrop(new Filter() {
#Override
public boolean accept(Object o) {
return !((OntProperty) o).listSuperProperties(true).toList().isEmpty();
}
}));
while (i.hasNext()) {
joinResource(rootTreeNode, (OntProperty) i.next(), new ArrayList(), OntProperty.class, domContent);
}
return treeModel;
}
private static Iterator getAlphabeticalIterator(ExtendedIterator ei) {
List l = ei.toList();
Collections.sort(l, new Comparator<OntResource>() {
#Override
public int compare(OntResource o1, OntResource o2) {
return (o1.getLocalName().compareTo(o2.getLocalName()));
}
});
return l.iterator();
}
private static DefaultMutableTreeNode getRoot() {
DefaultMutableTreeNode rootTreeNode = new DefaultMutableTreeNode();
ClassNodeUserObject rootObject = new ClassNodeUserObject(rootTreeNode);
rootObject.setExpanded(true);
rootTreeNode.setUserObject(rootObject);
return rootTreeNode;
}
private static void joinResource(DefaultMutableTreeNode parent, OntResource res, List occurs, Class c, Document domContent) {
DefaultMutableTreeNode branchNode = new DefaultMutableTreeNode();
SemanticNodeUserObject branchObject = (c.equals(OntClass.class))
? new ClassNodeUserObject(branchNode) : new PropertyNodeUserObject(branchNode);
branchObject.setOntResource(res);
branchObject.setExpanded(false);
branchObject.setLeaf(true);
// optimalizace: v pripade prazdneho souboru bez parsovani, aktualizace barev
if (domContent != null) {
setColorToNode(branchObject, domContent);
}
branchNode.setUserObject(branchObject);
parent.add(branchNode);
// rekurze
if (res.canAs(c) && !occurs.contains(res)) {
ExtendedIterator ei = (c.equals(OntClass.class)) ? ((OntClass) res).listSubClasses(true)
: ((OntProperty) res).listSubProperties(true);
branchObject.setLeaf(!ei.hasNext());
for (Iterator i = getAlphabeticalIterator(ei); i.hasNext();) {
OntResource sub = (OntResource) i.next();
occurs.add(res);
joinResource(branchNode, sub, occurs, c, domContent);
occurs.remove(res);
}
}
}