Sunday 27 December 2020

Constructors and Object Literals

In C# we can combine constructors expecting parameters and Object literals without a problem, like this:


class Person
{
	public string Name {get; set;}
    
       public int Age{get; set;}

       public string Country {get; set;}
       
       public Person(string name, int age)
       {
       	this.Name = name;
       	this.Age = age;
       }
}


var p3 = new Person("Francois", 2)
            {
                Country = "France"
            };

However, the above contructor+literal is not possible in JavaScript. Hopefully, it's really simple to do something similar with Object.assign:


class Person{
	constructor(name, age){
		this.name = name;
		this.age = age;
	}
    
    doGreet(greeting){
		return `${greeting}, I'm ${this.name} and I am ${this.age}`;
	}
}

//Obviously this is not valid JavaScript syntax
//let p1 = new Person("Francois", 2){
//	country: "France"
//};


let p1 = Object.assign(new Person("Francois", 2), {country: "France"});

console.log(JSON.stringify(p1, null, "\t"));

//this is not OK, we miss the Person [[prototype]] (hence, the methods) in the resulting object.
//let p0 = {...new Person("Francois", 2), ...{country: "France"}};

Notice that in this case we have to use Object.assign rather than the Object spread operator (...), as we would be missing the Person [[prototype]] in the resulting object.

Automatic Properties

Automatic Properties have evolved a bit over the years as new C# versions were released and I think I'll summarize here its different features.

The most common, basic case is this:


public string Name {get; set;}

Notice that the C# compiler creates a private, backing field for the property: <Name>k__BackingField.

We can also mark the setter as private:


public int Age{get; private set;}

In C# 6 two features where added: Automatic Property Initializers:


public string Country {get; set;} = "Unknown";

And Getter Only Autoproperties:


    //immutable, can be set also from constructor
    public string Dni {get;} = "Unknown";
    public string ID {get;}
    
    //use examples:
    public Person(string dni)
    {
    	this.ID = "unknownID";
    	this.Dni = dni;
    }

In the above case, the compiler no longer generates a setter. The private backing field is directly set, either in that assignment, or in the class constructor.

Finally, C# 9, paying further attention to the Immutability trend, has added Init only setters.


    //immutable, can be set also from constructor and from object literal
    public string MotherLanguage {get; init;} = "Unknown";
    
    //use examples:
    public Person(){}
    public Person(string motherLanguage)
    {
    	this.MotherLanguage = motherLanguage;
    }
    var p2 = new Person
    {
        MotherLanguage = "Francais"
    };

This "init" does not involve any addition at the bytecode level, it's just translated into a normal setter. The interesting thing with it is that it can be set not only inline or in the constructor, but also from an Object literal. Contrary to the previous, "Getter only autoproperties" where I said that if set from the constructor it's done by directly setting the private backing field, here, both from the constructor or the Object literal, the compiler emits a call to the setter.

Regarding my statements about getters being or not being generated, the backup fields and so on... I've been using AvaloniaILSpy, an excellent multiplatform frontend to ILSpy. I've been using it on my Ubuntu laptop and it runs nicely.

Saturday 19 December 2020

Extract Parameter Names in JavaScript

After publishing my previous post I realised there was a nice way to improve my "joinCollections" funtion, getting rid of the 2 "alias" parameters. First let's see the code again:


function joinCollections(collection1, collection2, idSelectorFn1, idSelectorFn2, alias1, alias2){
    let result = [];
    collection1.forEach(it1 => {
        let id1 = idSelectorFn1(it1);
        collection2.forEach(it2 =>{
            if (id1 === idSelectorFn2(it2))
                result.push({
                    [alias1]: it1,
                    [alias2]: it2
                });
        });
    });
    return result;
}

let persons = joinCollections(employees, 
    students, 
    employee => `${employee.firstName}-${employee.lastName}`, 
    student => `${student.firstName}-${student.lastName}`,
    "employee",
    "student"
)

As you can see we are using the same value as "alias" and as the parameter name in the selector funtion. Of course we could have done differently (employee/emp...), but there's not any reason for that. The alias and the parameter refer to the same thing, whatever thing we have stored in the collection.
In JavaScript we can get access to the parameter names of a function just by converting the function to string and extracting the names from the function signature. Hence, we can easily extract the alias from the selector function, just like this (code specific for an arrow function)
selectorFn.toString().split("=>")[0].trim();


function joinCollections2(collection1, collection2, idSelectorFn1, idSelectorFn2){
    let getAlias = selectorFn => selectorFn.toString().split("=>")[0].trim();
    let [alias1, alias2] = [idSelectorFn1, idSelectorFn2].map(getAlias);

    let result = [];
    collection1.forEach(it1 => {
        let id1 = idSelectorFn1(it1);
        collection2.forEach(it2 =>{
            if (id1 === idSelectorFn2(it2))
                result.push({
                    [alias1]: it1,
                    [alias2]: it2
                });
        });
    });
    return result;
}

let persons = joinCollections(employees, 
    students, 
    employee => `${employee.firstName}-${employee.lastName}`, 
    student => `${student.firstName}-${student.lastName}`
)

The call to joinCollections is now much cleaner.

This post has made me think again about the difference between arguments and parameters. It's perfectly explained here:

A parameter is the variable which is part of the method’s signature (method declaration). An argument is an expression used when calling the method

If you check the comments there's one question that also came to my mind, the array-like object arguments that we have inside javascript functions, shouldn't it have been called parameters?

No, it should not. That object gives us access to what the funcion has been passed/has received in that invocation, not to the list of parameters in its signature. The signature can have x parameters and we can pass over "y" values. arguments gives us access to those "y" values.

Sunday 13 December 2020

Join JavaScript Arrays

The other day I needed to join values from 2 javascript arrays, same as if I were joining values from 2 Database tables. In C# we can join values in collections by means of Linq to Objects and its Join method. In JavaScript I'm not aware of Lodash providing something similar, but it's pretty simple to implement, so that's what I've done.

The most important thing is what should I return in the resulting array after joining the 2 collections so that it's easy to apply on it .map (select) and .filter(where). The best option that came to mind was putting each joined pair in an object with 2 keys, with each key provided as a sort of "alias" in the call to join. OK, I better show the code:


function joinCollections(collection1, collection2, idSelectorFn1, idSelectorFn2, alias1, alias2){
    let result = [];
    collection1.forEach(it1 => {
        let id1 = idSelectorFn1(it1);
        collection2.forEach(it2 =>{
            if (id1 === idSelectorFn2(it2))
                result.push({
                    [alias1]: it1,
                    [alias2]: it2
                });
        });
    });
    return result;
}

With that, we can easily access the 2 objects being joined for each "row" in order to do additional filtering or for mapping into a single resulting object.

Given the following inputs:


let employees = [
    { 
        firstName: "Terry", 
        lastName: "Adams", 
        role: "FrontEnd Developer"
    },
    { 
        firstName:"Charlotte", 
        lastName:"Weiss", 
        role: "Systems Administrator" 
    },
    { 
        firstName:"Magnus", 
        lastName:"Hedland", 
        role: "Psycologist"
    }, 
    { 
        firstName:"Vernette", 
        lastName:"Price", 
        role: "Shop Assistant"
    }
];

var students = [
    { 
        firstName:"Vernette", 
        lastName:"Price", 
        studies: "Philosophy"
    },
    { 
        firstName:"Terry", 
        lastName:"Earls", 
        studies: "Computer Engineering"
     },
     { 
         firstName:"Terry", 
         lastName:"Adams", 
         studies: "Computer Engineering"
    } 
];

We can obtain a list of Person objects with their full name, job and studies.


let persons = joinCollections(employees, 
    students, 
    employee => `${employee.firstName}-${employee.lastName}`, 
    student => `${student.firstName}-${student.lastName}`,
    "employee",
    "student"
).map(ob => {
    return {
        fullName: `${ob.employee.firstName} ${ob.employee.lastName}`,
        job: ob.employee.role,
        studies: ob.student.studies
    };
});

console.log("-- persons:\n " + JSON.stringify(persons, null, "\t"));

let persons2 = joinCollections(employees, 
    students, 
    employee => `${employee.firstName}-${employee.lastName}`, 
    student => `${student.firstName}-${student.lastName}`,
    "employee",
    "student"
)
.filter(ob => ob.employee.role === "FrontEnd Developer")
.map(ob => {
    return {
        fullName: `${ob.employee.firstName} ${ob.employee.lastName}`,
        job: ob.employee.role,
        studies: ob.student.studies
    };
});

Different from what we do in SQL, if we want to join more than 2 collections, we should join 2 of them, map the resulting pairs to a normal object, and then do the next join. I mean, given a third collection with salaries data, to join it to the previous employees and students data we first should do the join and map done in the previous step, and then do an additional join, like this:


let salaries = [
    {
        job: "FrontEnd Developer",
        amount: 40000 
    },
    {
        job: "Shop Assistant",
        amount: 20000 
    }
];

let persons = joinCollections(employees, 
    students, 
    employee => `${employee.firstName}-${employee.lastName}`, 
    student => `${student.firstName}-${student.lastName}`,
    "employee",
    "student"
).map(ob => {
    return {
        fullName: `${ob.employee.firstName} ${ob.employee.lastName}`,
        job: ob.employee.role,
        studies: ob.student.studies
    };
});

let personsWithSalaries = joinCollections(
    persons,
    salaries,
    person => person.job, 
    salary => salary.job,
    "person",
    "salary"
).map(ob => {
    return {...ob.person, ...ob.salary};
});

As usual, I've uploaded it into a gist

Monday 7 December 2020

Linux Memory Values

I've been trying to understand lately memory consumption information in Linux and I'll share my findings here.

My personal laptop has 8 GB of RAM (for sure, I can see it in the Bios), but the integrated Graphics card is taking 2.1 GB (and my Bios does not allow me to configure and reduce it!!!). The different programs that I've used in Linux to view my memory status only show the physical memory available to the system discounting those reserved 2.1 GB, hence 5.9 GB, and I have not found a way in Linux to see that the real physical amount of memory in my system is 8 GB.

I have to admit that things are a bit more clear in Windows. Task manager will show 6GBs in the main view, but at least it also has a "Hardware reserved: 2.1 GBs" reading. Furthermore, the "Windows About" window shows: Installed RAM 8.00 GB (5.92 GB usable).

The three main programs that I use to check my memory are the Ubuntu System Monitor and the top and free -m commands.

The information in the System Monitor is pretty straight forward. A 2 colors representation (as when checking a hard disk usage), and a "used" percentage. There is also the "Cache" value... that can seem quite more misterious, we'll understand what it represents in the next paragraphs.

The information displayed by top can be particularly confusing if we just read the first (total) and second (free) values. We should not care much about that "free", we should read just to the end to find the "avail Mem" value, that's what really matters in terms of how much memory we still have available (many of us would call it "free", but "free" has a different meaning in memory terms).

If we run free -m we really get the full picture, but we need some extra knowledge to interpret it.

              
		total        used        free      shared  buff/cache   available
Mem:           5920        1908        1704         112        2307        3610
Swap:          8092           0        8092

used is what we expect, the memory currently in use by our system. available is, as I've said for "top", what we really care in terms of how much memory my programs can still use without having to resort to swapping. And then we mainly have "free" and "buff/cache" (and "shared", but this is a small value, it represents the space used for tmpfs)

The main point to understand buff/cache and free is to be aware that Linux tries to take advantage of our RAM as much as possible (this is the same for Windows, but as Task Manager does not show any information about it, there's not much way for confusion). For that, it will store in memory pages read from disk, so that if we need them again we can take them from memory rather than reading them again from the slow disk. This is called Page Cache-Disk Cache. This is roughly what we see in free -m as buff/cache, and "free" is basically: total - used by programs - used by buff/cache - shared.

In computing, a page cache, sometimes also called disk cache,[2] is a transparent cache for the pages originating from a secondary storage device such as a hard disk drive (HDD) or a solid-state drive (SSD). The operating system keeps a page cache in otherwise unused portions of the main memory (RAM), resulting in quicker access to the contents of cached pages and overall performance improvements. A page cache is implemented in kernels with the paging memory management, and is mostly transparent to applications. Usually, all physical memory not directly allocated to applications is used by the operating system for the page cache. Since the memory would otherwise be idle and is easily reclaimed when applications request it, there is generally no associated performance penalty and the operating system might even report such memory as "free" or "available".

Another interesting point is the swap used value. In my case it's 0, which looks quite natural as I have plenty of available RAM, but sometimes values could be slightly more confusing, as explained here:

Sometimes the system will page something out (for whatever reason). If later that page is moved back to memory for a read operation, the copy in swap space is not deleted. If the same page is later paged out again, without being changed, it can do so without writing to the dis