Does Nim support types with immutable fields? - immutability

In C# you can do this
public class Foo
{
public string Name { get; private set; }
public Foo(string name)
{
Name = name;
}
}
public static void Main()
{
var foo = new Foo("Foo Object");
Console.WriteLine(foo.Name);
// Will not compile
// foo.Name = "Bar Object";
}
Can you do the same (or something that has the intended effect) in Nim?

Nim doesn't have encapsulation on type scope (and it wouldn't make sense since Nim is not an object oriented language, all data processing is separated from the data itself).
The same effect can be achieved using module-scope encapsulation like this:
foo.nim:
type Foo* = ref object
name: string
proc newFoo*(name: string): Foo =
new result
result.name = name
proc name*(self: Foo): string =
self.name
main.nim:
import foo
let f = newFoo("Foo Object")
echo f.name
# Error: attempting to call undeclared routine: 'name='
# f.name = "Bar Object"

Related

Improving DSL syntax

To start learning design of DSLs using Kotlin language features, I have
the attempt below at a toy DSL for creating groups of members with members
having names. I am looking for pointers/hints on the following
How can I avoid having to separate groups by a semicolon, if no semicolon the compiler gives
Groups.kt:31:45: error: unresolved reference: member
val grp = group { member { name ("Bob") } member { name ("Sandy") } }
Can i get to use a lambda for setting name instead of function call?
Can I avoid having to have name be mutable in class MEMBER?
My code is
fun group(create: GROUP.() -> Unit) = GROUP().apply(create)
class GROUP {
private val members = mutableSetOf<MEMBER>()
fun member(create: MEMBER.() -> Unit) {
val member = MEMBER()
member.create()
members.add(member)
}
override fun toString() = members.toString()
}
class MEMBER() {
var name = ""
set(value) {
field = value
}
fun name(nameToSet: String) {
name = nameToSet
}
override fun toString() = "MEMBER(" + name + ")"
}
fun main(args: Array<String>) {
val grp = group { member { name ("Bob") }; member { name ("Sandy") } }
println(grp)
}
Currently the output of above code is
[MEMBER(Bob), MEMBER(Sandy)]
How can I avoid having to separate groups by a semicolon
By using the idiomatic format, using separate lines. After all, the whole point of a DSL is to make the code very readable by showing the hierarchical structure, and doing everything on a single line defeats the wole purpose:
val grp = group {
member {
name ("Bob")
}
member {
name ("Sandy")
}
}
Can I get to use a lambda for setting name instead of function call?
It would be more logical and idiomatic to remove the name function and to simply assign a value to the property:
name = "Bob"
But yes, you can also replace your name function by
fun name(block: () -> String) {
this.name = block()
}
and use
name {
"Sandy"
}
Can I avoid having to have name be mutable in class MEMBER?
Yes: the lambda passed to the member() function would customize an additional MemberBuilder class, that would be mutable, but would allow to create an immutable MEMBER:
fun group(create: GROUP.() -> Unit) = GROUP().apply(create)
class GROUP {
private val members = mutableSetOf<MEMBER>()
fun member(configure: MemberBuilder.() -> Unit) {
val memberBuilder = MemberBuilder()
memberBuilder.configure()
members.add(memberBuilder.build())
}
override fun toString() = members.toString()
}
class MEMBER(val name: String) {
override fun toString() = "MEMBER($name)"
}
class MemberBuilder {
var name = "";
fun build() = MEMBER(name)
}
fun main(args: Array<String>) {
val grp = group {
member {
name = "Bob"
}
member {
name = "Sandy"
}
}
println(grp)
}
Also, note that classes, by convention, are PascalCased, not ALL_CAPS.

How do I specify the field in an object to update with a string or some other pointer c#

I'm just learning visual c# in visual studio
Ok, so I have a ton of data fields in a form, and then I want to write the handlers to all call one main method, update, which then updates a resultsEntry object, which encapsulates a bunch of uint variables with various names.
How do I write an update method to put in either the results object, or the update method that will take the name of the variable in resultsEntry as a string, and the integer to update it with, and then update that field.
Basically, I need to do a
resultsEntry.(inStringHere) = inValueHere;
where resultsEntry is the object being updated, the inStringHere specifies the field to be updated, and the inValueHere represents the integer value to assign to it.
Thanks!
Sam French
You have two challenges,
Setting a field/property in class using a string (the focus of your question). This will be accomplished using reflection.
Converting values to the type in your class (this may not be a problem for you, you may have 'typed' values. I have an ugly solution because this is not the main focus of your question.
Setting a property by name (see comments preceded with '**'):
static class Program
{
// A 'ResultEntry' type
public class ResultEntry
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
static void Main()
{
// some tuples Field1 = Property Name; Field2 = Raw Value (string)
List<Tuple<string, string>> rawEntries = new List<Tuple<string, string>>() {
new Tuple<string,string>("ID", "1")
, new Tuple<string, string>("FirstName", "George")
, new Tuple<string, string>("LastName", "Washington")
};
ResultEntry resultEntry = new ResultEntry();
// ** Get MemberInfo's for your ResultEntry. Do this once, not for each instance of ResultEntry!
MemberInfo[] members = resultEntry.GetType().GetMembers(BindingFlags.Public | BindingFlags.Instance);
// Iterate over input
foreach (var raw in rawEntries)
{
// find a MemberInfo (PropertyInfo) that matches your input 'PropertyName'
MemberInfo member = members.FirstOrDefault(m => m.MemberType == MemberTypes.Property && m.Name == raw.Item1);
if (member != null)
{
// if you input is typed you will not have to deal with
// conversion of the string to the actual type of the property
object val = raw.Item2.MyConverter(((PropertyInfo)member).PropertyType);
// ** set the value in 'ResultEntry'
((PropertyInfo)member).SetValue(resultEntry, val, null);
}
}
Console.WriteLine(string.Format("Result Entry: ID = {0}, FirstName = {1}, LastName = {2}", resultEntry.ID, resultEntry.FirstName, resultEntry.LastName));
Console.ReadLine();
}
}
If you need to deal with converting raw string input to type (e.g. string to int), then is just one strategy...
public static class Extensions
{
public static object MyConverter(this string rawValue, Type convertToMe)
{
// ugly, there are other strategies
object val;
if (convertToMe == typeof(Int32))
val = Convert.ToInt32(rawValue);
// ... add other type conversions
else
val = rawValue;
return val;
}
}
Hope this helps.

Linq expression over a list of derived types

I am trying to write a Linq expression that checks against property in a derived class, but the list is made up of members from a base class. Example code below. The 2nd line of the Process method starting with 'var list' does not compile, but I am not sure what syntax I should use to make it valid?
public class Manager
{
public void Process()
{
Base[] stuff = { new Derived() { Id = "1", Name = "me" } };
var list = stuff.Where<Derived>(d => d.Name == "me");
}
}
public class Base
{
public string Id { get; set; }
}
public class Derived : Base
{
public string Name { get; set; }
}
If you know the list has only Derived, you can use the Cast<T> method:
var list = stuff.Cast<Derived>().Where(d => d.Name == "me");
If there are only some Derived, you can use OfType<T>:
var list = stuff.OfType<Derived>().Where(d => d.Name == "me");
In that case, the non-Derived objects will be skipped.

How do I create a custom Select lambda expression at runtime to work with sub classes

If I have following type hierarchy:
abstract class TicketBase
{
public DateTime PublishedDate { get; set; }
}
class TicketTypeA:TicketBase
{
public string PropertyA { get; set; }
}
class TicketTypeB:TicketBase
{
public string PropertyB { get; set; }
}
and many more TicketTypes : TicketBase
and want to create a function which selects any property e.g. PropertyA from any ticket type e.g. TicketTypeA
I wrote this function:
private Func<TicketBase, String> CreateSelect(Type t, String FieldName)
{
var parameterExp = Expression.Parameter(t, "sel");
var fieldProp = Expression.PropertyOrField(parameterExp, FieldName);
var lambda = Expression.Lambda<Func<TicketBase, String>>(fieldProp, parameterExp);
return lambda.Compile();
}
and call it on a List<TicketBase> Tickets like so:
Type typeToSelectFrom = typeof(TicketTypeA);
String propertyToSelect = "PropertyA";
Tickets.Select(CreateSelect(typeToSelectFrom, propertyToSelect));
I get the following ArgumentException:
ParameterExpression of type 'TicketTypes.TicketTypeA' cannot be used for delegate parameter of type 'Types.TicketBase'
Anyone know how to fix this?
Well, one option is to include a cast, e.g.
private Func<TicketBase, String> CreateSelect(Type t, String FieldName)
{
var parameterExp = Expression.Parameter(typeof(TicketBase), "sel");
var cast = Expression.Convert(parameterExp, t);
var fieldProp = Expression.PropertyOrField(cast, FieldName);
var lambda = Expression.Lambda<Func<TicketBase, String>>(fieldProp,
parameterExp);
return lambda.Compile();
}
So that calling CreateSelect(typeof(TicketTypeA), "PropertyA") is equivalent to:
Func<TicketBase, string> func = tb => ((TicketTypeA)tb).PropertyA;
Obviously that's going to fail if you apply it to a TicketBase value which refers to (say) a TicketTypeB, but it's hard to avoid that, if you've got a List<TicketBase> or something similar.

Update one object with another in LINQ

I use LINQ to expose database objects to my application. Also in this application I get an object from my database called 'foo' like so.
public static Foo Get(int id)
{
MyDataContext db = new MyDataContext ();
Foo foo1 = (from f in db.Foos
where f.foo_id = id
select f).SingleOrDefault();
return foo1;
}
Now, if I change foo and want to update it without going through each field explicitly - I want to avoid this.
public static Foo Update(Foo foo)
{
MyDataContext db = new MyDataContext ();
Foo foo1 = (from f in db.Foos
where f.foo_id = foo.foo_id
select f).SingleOrDefault();
if(foo1 != null)
{
foo1.foo_nm = foo.foo_nm;
...
db.SubmitChanges();
}
}
Is there a way I can do something like in the entity framework:
foo1.UpdateVales(foo);
Create your own cloning method that copies all the properties you're interested in.
Alternatively you can use reflection to find all public properties and loop through them.
LINQ is no help here.
Here's a very simple (and also inefficient) extension function that can get you started (Make sure you import System.Reflection and System.Linq):
public static void GetDataFrom<T>(this T ObjToCopyTo, T ObjToCopyFrom) where T : class {
foreach (var property in ObjToCopyTo.GetType().GetProperties().Where(x => x.CanWrite))
property.SetValue(ObjToCopyTo, property.GetValue(ObjToCopyFrom, null), null);
}
You will probably find that you will have to put some special cases in for things like the primary keys, and may decide you do not want to copy every property exactly, but hopefully this shows the idea behind VVS's answer.
If you have linqpad installed you can play around with this idea with the following script:
void Main()
{
var foo = new Helper.Foo() {
field1 = "hi",
field2 = 5,
field3 = 3.14,
field4 = 'm'
};
var foo2 = new Helper.Foo();
foo.Dump("Foo Before");
foo2.Dump("Foo2 Before");
foo2.GetDataFrom(foo);
foo.Dump("Foo After");
foo2.Dump("Foo2 After");
}
public static class Helper {
public class Foo {
public string field1 { get; set; }
public int field2 { get; set; }
public double field3 { get; set; }
public char field4 { get; set; }
}
public static void GetDataFrom<T>(this T ObjToCopyTo, T ObjToCopyFrom) where T : class {
foreach (var property in ObjToCopyTo.GetType().GetProperties().Where(x => x.CanWrite))
property.SetValue(ObjToCopyTo, property.GetValue(ObjToCopyFrom, null), null);
}
}
I hope this helps!
I use automapper to avoid the heavy lifting to update the DB with MVC models, should work for mapping to the same object type and comes in handy for these sorts of coding styles.
After installing automapper ...
public ActionResult Example(TableModel model)
{
..
Mapper.CreateMap<TableModel, Table>();
Table myTable = new Table();
Mapper.Map(model, myTable);
...
}

Resources