• Dependency injection in Python

    Since Python type hints are introduced, they have made complex Python code-bases much more readable and easier to maintain - especially combined with newer static analysis tools such as mypy or pylint. However, even with these tools, Python is still a dynamic language. When using a dynamic language on a larger application (>5k LOC), the ability to do whatever we wanted any where and any time is more of a curse than a blessing.

    In this post, I wanted to discuss several options of implementing loosely coupled code in large Python codebases that I have played around with and the final solution of dependency injection based pattern I ended up deciding on.

    Read more
  • Javascript oddities

    A collection of weird things in Javascript:

    1. var scoping rules

    for (var i = 0; i < 3; ++i)
    {
    	const log = () => {
      	console.log(`a ${i}`);
      }
      setTimeout(log, 100);
    }
    
    for (let i = 0; i < 3; ++i)
    {
    	const log = () => {
      	console.log(`b ${i}`);
      }
      setTimeout(log, 100);
    }
    

    The output here is:

    "a 3"
    "a 3"
    "a 3"
    "b 0"
    "b 1"
    "b 2"
    

    Why does var cause it to print 3?

    2. const in Javascript does not mean the same as C/C++. Example:

    const value = 3;
    value = 4; // error, cannot override a constant
    value += 3; // error
    
    const obj = {a : 3};
    obj.a += 3; //allowed
    obj.a = 5; //allowed
    

    Turns out const in Javascript is more of a “const” reference like const & in C++. It does not mean the value itself is constant - just the reference to the array cannot be changed.

    3. Converting time formats can be tricky

    Suppose you have a time in yyyy-mm-DD format and you want it in mm/DD/yyyy format.

    new Date('2016-06-05').
      toLocaleString('en-us', {year: 'numeric', month: '2-digit', day: '2-digit'})
    
    // Output:
    >>> '06/04/2016'
    

    Wait, what happened?, I asked for 2016-06-05 in mm/dd/YYYY but it gave me 06/04/2016 instead! This because all dates by default assumes it’s GMT time, when you convert it to a local timezone, you might get a different date.

    The moment library fortunately makes this a lot easier.

    var date = new Date('10/01/2021');
    var formattedDate = moment(date).format('YYYY-MM-DD');
    

    If we don’t want some extra dependency, it’s probably easier to just not convert the date into a Javascript Date obj and directly do string operations on it to get it to the format you want. Example:

    function reformatDateString(dateString) {
        //reformat date string to from YYYY-MM-DD to MM/DD/YYYY
        if (dateString && dateString.indexOf('-') > -1) {
            const dateParts = dateString.split('-');
            return `${dateParts[1]}/${dateParts[2]}/${dateParts[0]}`;
        }
        return dateString;
    }
    
    Read more
  • Rust like enums in C++

    While browsing the excellent modern C++ reactive console UI library FTXUI, I noticed this piece of code in how the events are typed/handled.

    // event.hpp
    struct Event {
      // --- Constructor section ---------------------------------------------------
      static Event Character(char);
      static Event CursorReporting(std::string, int x, int y);
      // Other constructor methods
    
      // --- Arrow ---
      static const Event ArrowLeft;
      static const Event ArrowRight;
      static const Event ArrowUp;
      static const Event ArrowDown;
      // .... Other definitions etc....
    

    My immediate reaction to this is that this feels weird - partially because I am not used to the author’s C++ style, in addition, the combination of static member variables sharing the parent-type, and static methods for constructors are really confusing to read.

    Let’s dive into it to see how things work.

    Read more
  • Python testing ecosystem

    Read more
  • Common, stupid, but non-obvious C++ mistakes I made

    Internet consensus tends to label C++ as a hard language; I like to think Cpp is a “deep” language. There are always rooms for improvement - doesn’t matter how long you have been coding in C++. The expressiveness and the depth of the language is double-edged. It is what makes C++ great, but also makes it daunting for new users. These are the mistakes I’ve made in my daily usage of C++. I hope they can be useful for other people to avoid them in the future.

    1. Capture by reference on transient objects

    Callbacks (lambda functions, function pointers, functors, or std::bind on static functions) are a common paradigm when you work with message queues, thread pools, or event based systems. Lambda and closures give you a lot of power - but too much power could often cause problems, consider the following code:

    Read more
  • Rich D3 interactivity in Jekyll posts

    This is me trying to reproduce the results in this Stack Overflow post and Dan Cole’s blog.

    Things to keep in mind:

    • Include morley.csv (Search local JavaScript for /morley.csv)
    • Include D3.js
    • Include box.js
    • Include the local CSS and JavaScript

    Check out the code for this post on GitHub.

    Read more
  • Maximize the luck surface area

    Hacker News recently had a post about “maximizing luck surface area”. Jason Roberts made a point that seemingly random success that people experience that most people attributes to luck, is really a game of probability.

    While most people follow the axiom of doing “good work” by spending years going through school, honing their craft, and then practicing those crafts and skills to perfection at work (cough, programming languages, frameworks, design patterns, algorithms, etc.) Many people neglects the other important pre-requisites to success - letting others know about your work and building up the reputation for network effects.

    Read more
  • Using an Apple Silicon Macbook for C++/Python development

    The newest and latest (late-2020) Apple Macbook Air and Macbook Pro 13” with Apple Silicon has been out on the market for a while now. Recently, I had the priviledge of getting a Macbook Air with M1 chip as as a dev machine to test various things (c++, python, jupyter notebook) that I use.

    From the Youtube reviews (MKBHD) and various benchmarking websites (Toms’ Hardware, Daring Fireball), I already know that the performance of the M1 chips is really impressive at the given power consumption; and that people are getting ridiculous battery lifes on their M1 Macs. However, as someone that intends to use the Mac as a development daily driver, my main concern is how my workflow and toolchain will work with the new Apple Silicon and ARM64 instruction set. After a few weeks of tinkering and exploration, I think it is safe to say that Apple has done an incredible job to ensure smooth transition to the new hardware, and that AMD/Intel/Microsoft or any other hardware manufacturer should be shitting their pants right now for the on-slaught that’s about to come.

    Read more
  • Passing by const reference

    While working in any large C++ project, we often deal with having to write small utility functions that takes in some temporary and then perform some operation on it to return a transformed variable. For example

    std::string append_path(const std::string& basepath, const std::string& child_path)
    {
        return basepath + "/" + child_path;
    }
    
    // Invoking this function:
    const std::string basepath = "/var/tmp";
    const std::string text_file = "some_file.txt";
    const std::string new_path = append_path(basepath, text_file); // this works
    const std::string other_new_path = append_path(basepath, "some_other_file.txt"); // this also works
    

    Does this seems strange to you? We are requiring the variable to be passed in by reference. The "some_other_file.txt" argument in the 2nd invocation of the argument is a “r-value”, and we are able to refer to the content of this r-value string as a reference to some variable.

    It turned out, as Herb Sutter explained it here:

    The C++ language says that a local const reference prolongs the lifetime of temporary values until the end of the containing scope, but saving you the cost of a copy-construction (i.e. if you were to use an local variable instead).

    So, effectively, the r-value life-time is extended to the function scope when it is being invoked as an argument to a function immediately after its definition.

    Now I can rest easy, knowing that the behavior of my program won’t depend on how aggressive the compilers optimize or reuse the memory of variables that are no longer considered “needed” by scoping rules.

    Read more
  • Abstraction All the Way Down

    Programming or any problem solving skill is really all about distilling complex problems into simpler abstractions. The art of creating elegant abstractions is a skill that developers must acquire on their journey to master software craftsmanship. Terse abstractions that fully describes a problem helps reduce cognitive burden, allowing the developer to focus on what really matters in the code.

    Read more
  • Embedding icon into GUI executables for MacOS / Windows via cmake

    CMake while being arcane and quirky in its own way, is currently the standard cross-platform compilation platform for C++/C build systems. I think the power of CMake comes from all the community contributions and the knowledge base built up over the years.

    I recently worked on a project to migrate it from an archaic Perl build system into the land of CMake. Following modern CMake practices really made dependency management a breeze (i.e. target based compilation flag specification, target based linking, transient header propagation via INTERFACE/PUBLIC/PRIVATE, generator expressions to optionally specify different compiler warning / optimization levels)

    One of the things that took a little while for me to figure out is how to embed a GUI based application an application icon that is in a cross-platform friendly method. I googled around and really didn’t come across a simple enough solution, so I decided to roll my own.

    Read more
  • SFINAE in C++11 and beyond

    As C++ coder, sooner or later you will encounter elements of meta-programming. It might be as simple a STL container. Or it might be a full blown template class that takes variadic arguments. I, myself, have also taken this journey. As I ventured deeper into meta-programming, acronyms such as CRTP, SFINAE really piqued my interest. Today, let’s talk about SFINAE.

    SFINAE stands for “substitution failure is not an error”, and there has been numerous articles, stack overflow questions and blog posts on this topic:

    Read more
  • Go channels in Cpp, part 2

    In this part 2 of the Go channel series, I will expand the Channel<T> class we developed to support multiple elements, range for loops and asynchronous operations.

    Part one of this series, where we built a simple Go channel with similar synchronization behavior is available here.

    Buffered channels are desirable in many parallel applications such as work queues, worker/thread pools, MCMP (multiple consumers/producers) patterns.

    Read more
  • Go channels in Cpp, part 1

    Go channels is the de-facto synchronization mechanism in Go. They are the pipes that connect concurrent go routines. You can send values into channels from one goroutine and receive those values into another goroutine. Having channels have made writing multi-threaded concurrent programs really simple in Go. In this series, I wanted to see if it’s possible to re-create it in cpp.

    Read more
  • Where did the heap memory that I just freed go?

    Heap memory allocation via new and delete (or malloc or free for C) are unavoidable for more complex, large scale programs. However, it is a common misconception that free/delete will actually free the memory back to the operating system for other processes to use.

    This is because there are actually two different types of memory allocation happening behind a malloc/new call. The first type, reserved usually for smaller allocations (less than 100 kb) uses sbrk(), which is a traditional way of allocating memory in UNIX – it just expands the data area by a given amount. The second type uses mmap() to allocate memory for larger chunks of memory. mmap() allows you to allocate independent regions of memory without being restricted to a single contiguous chunk of virtual address space. A memory mapped region obtained through mmap() upon unmapping will immediately release the memory back to the OS, whereas sbrk() will keep the released memory within the process for future allocations.

    Read more