Sunday 27 November 2022

Try Expressions

I've recently found that Kotlin supports try-catch-finally expressions (in the same vein as switch expressions). They seem particularly useful to me when executing a block that will assign to a variable or assign a default if the block fails, like this:



fun main (args: Array) {
  val str="23"
  val a: Int? = try { str. toInt () } catch (e: NumberFormatException) {-1}
  println (a)
}


I think this is the first time I see this feature in a programming language, and as usual I've been thinking about how to simulate it, in this case in JavaScript. We can easily simulate the try-catch expression with a tryFn function (emulating try-catch-finally would be more complicated).



function tryFn(fn, exceptions, onErrorFn){
    try{
        return fn();
    }
    catch (error){
        if (exceptions.some(exception => error instanceof exception)){
            return onErrorFn(error)
        }
        else{
            throw error;
        }
    }
}

//val = tryCatch(fn1, [Error1, Error2], onErrorDefaultFn)


We can use this function like this:



class InvalidUrlError extends Error{}
class InvalidPostError extends Error{}
class InvalidUserError extends Error{}


function getPost(url, postId, user){
    if (!url)
        throw new InvalidUrlError("Wrong URL")
    if (!postId)
        throw new InvalidPostError("Wrong Post")
    if (!user)
        throw new InvalidUserError("Wrong User")
    return `Post ${postId} by {user} content`;
}

function formatPost(post){
    return `[[[${post}]]]`;
}

let infos = [
    ["server.org", "1", "xuan"],
    [null, "1", "xuan"],
    ["server.org", null, "xuan"],
    //["server.org", "2", null],
    ["server.org", "3", "xuan"]
]


for (let info of infos){
    let post = tryFn(() => formatPost(getPost(...info)),
        /*catch*/ [InvalidUrlError, InvalidPostError], (ex) => {
            console.log(`caught error: ${ex.constructor.name}`);
            return "No Post"
        } 
    );
    console.log(`post: ${post}`)
}


Well, not sure I will ever use it, but I think it's a valid attempt.

This reminds me a bit of cases where combining await and .catch() for async code rather than wrapping the async call in a try-catch makes the code cleaner. I'm talking about this

Saturday 19 November 2022

FIC Xixón 2021

Sort of a "deja vu". One year ago, when I was going to start to write a post for that year's edition (2021) of FIC Xixon (FICX edition number 59) I realised that I had not published anything about the previous, non-covid, edition (I'd had it partially written for almost 2 years but had forgotten to complete it), so I finished it and published it. Now, while starting my post for 60th edition (that ends today) I've just realised that in the end I had not written anything about the 59th edition... so I'm posting now a mini-summary of what I watched last year.

FIC Xixon 59 took place in one week of 2021 in a beautifully, massivelly rainy November. I only attended 3 films (that seems like a constant since I returned to Xixón in 2018). As I only intended to attend to screenings in Teatro Jovellanos I did not dig much into the program, I just checked what was on display there and came up with these 3 films that did fit my schedule:

  • Maitxable. A very powerful Spanish film. Based on a true story. Maixable, the widow of a Politician (Juan María Jáuregui) murdered by ETA accepts to meet one of the assasins, that while serving his prison sentence has come to regret his actions and moved away from the band.
    If you are interested in the bloody "Basque Conflict" that caused so much pain and suffering, you must watch the Spanish series Patria, that with its gloomy atmosphere perfectly reflects the tensions, contraditions, fanatism and fear that reigned in EuskaHerria for decades.
  • Integralde. Excellent Romanian film. Perfectly mixing hilarious moments with tension and sadness, all of it wrapped in the beauty of Romanian mountains and forests.
  • Bebia, a mon seul desir. A strange story set in a strange place (Georgia feels still rather "exotic" and mysterious to me), filmed in black and white with a rather arty feeling. I did not particularly like it, but do not consider it as a lost of time either.

Monday 14 November 2022

Python Optional Chaining Revisited

I've been thinking again about that Python missing feature (Optional Chaining) I wrote about in this post. It seems like there are no plans to approve the PEP-505 (None aware operators), as there are quite a few opponents to the syntax. I have to admit that it's true that coming across something like:
obj?.client?.getPosts?.("url")?[0]?["title]
is not particularly beautiful and goes rather against the "almost pseudocode" syntax ideal of Python, though anyway I think it's much better than a long chain of if's. Having just a safe_access function added to the standard library would be a good alternative. Thinking of that, I've realised that the implementation of such a function that I wrote for that post is rather stupid :-), does not work with indexing and has the terrible inconvenience of using strings for the attributes names.

The different access errors that we can get when trying to access "things" (attributes, indexing, invoking) on None, or on an object lacking such attributes or indexing or not being callable, etc are: TypeError, KeyError, IndexError, AttributeError, so why not to write our code like this:


try:
	first_title = obj.client.getPosts("url")[0]["title"]
except TypeError, KeyError, IndexError, AttributeError:
	first_title = None
	

Well, that's OK, but it's 4 lines vs 1 line if we had an optional chaining operator. So, let's put the try-catch in a function, and use a lambda to express the access chain, like this:


def safe_access(fn):
    try:
        return fn()
    except (TypeError, KeyError, IndexError, AttributeError):
        return None
        

first_title = safe_access(lambda: obj.client.getPosts("url")[0]["title"])


Honestly I think it looks quite good. Notice that I'm not passing the object being accessed as a parameter to the lambda, I'm directly trapping it as a closure variable. Having a function like this in functools would be even more convenient that implementing the "?" thing, as it would not involve any addition to the language syntax.

Thanks to looking into this topic again I've come across 2 very interesting ideas. One is the Maybe pattern, and its implementation in Python. The other one quite blew me away. An implementation of PEP-505 as a polyfill. So, how can you do that? Well, you can hook into the modules import process and do crazy stuff with them like transforming their source code before python compiles them to bytecodes. This way, you can add extra features to the language as far as you can then compile them to standard python. This is a very powerful feature but that seems rather unknown. The modules import process is documented here

Saturday 5 November 2022

Python Identity and Equality

There are quite a few things we should be aware regarding identity, equality and comparison in Python. I won't explain here the difference between identity (also known as reference equality, mainly in C#) and equality (also known, again mainly in C#, as value equality), it's a general Computer Sciences concept that you should already have clear before reading this post. I already talked about it quite a while ago.

In Python, For identity comparison we use the is and is not operators. They check if 2 variables point to the same object, so they hold the same memory location. ob1 is ob2 is the same as doing id(ob1) == id(ob2).

For equality comparison we use the == and != operators. The behaviour of == and != is determined by the __eq__ and __ne__ methods in the class of our object, so we can customize their behaviour (operator overloading) implementing them in our class. Otherwise, the attribute resolution algorithm we'll end up using object.__eq__ and object.__ne__. These default methods just do an identity/reference comparison. Obviously classes like str or int implement __eq__ and __ne__. This means that str.__eq__ is object.__eq__ is False. You can read more here

Because all types are (direct or indirect) subtypes of object, they inherit the default comparison behavior from object. Types can customize their comparison behavior by implementing rich comparison methods like __lt__(), described in Basic customization.

The default behavior for equality comparison (== and !=) is based on the identity of the objects. Hence, equality comparison of instances with the same identity results in equality, and equality comparison of instances with different identities results in inequality. A motivation for this default behavior is the desire that all objects should be reflexive (i.e. x is y implies x == y).

I've just talked about implementing the __ne__ method. Well, that's not necessary really, we only need to implement __eq__ to customize the equality behaviour for one class. != will try to find a __ne__ method in our instance, and as we have not implemented it it will end up in object.__ne__, that will call __eq__ in that instance (the method that we have implemented) and negate its result. You can find an in depth discussion here.

Python 3.x: indeed, the default implementation of __ne__ calls __eq__ and negates the result (but on the technical level there are some subtleties, please read on).

Hopefully, contrary to JavaScript, we could say that Python does not have type coercion/implicit conversion. I mean, the equality comparison implementations (__eq__, __ne__) in classes like int and str (or the __add__ method) will not automatically convert one type to another if it receives an object of a different type. In Python 5 == "5" is False, while in JavaScript it's True. In the same, way 3 + "5" in Python throws and Exception, while JavaScript converts the integer to string and returns "35".

in operator. The in operator is really useful and expressive. One should wonder how it works regarding value or reference equality. Well, answer gives such an excellent explanation. In short, "in" uses the __contains__ method defined in the container object. For standard containers __contains__ does this:

For container types such as list, tuple, set, frozenset, dict, or collections.deque, the expression x in y is equivalent to any(x is e or x == e for e in y).

Additional considerations. When comparing strings or numbers, we should always use "==" rather than "is". When checking if an object is None, and given that None is a singleton, in most cases using is or == would be equivalent, and is is considered better style. There could be some classes for which __eq__ has been implemented to make comparing to None as True, which I think is very unlikely. In those odd cases you should use ==, unless that you want to skip that odd behaviour...

Sort comparisons. Regarding the >, <, >=, <= comparisons, explains it pretty well.

Some polygloth notes: In Java we use the == operator for identity, and Object.equals (that we can override) for equality. In javascript it's commont to say that we have an identity operator === and an equality operator ==. As there is no operator overloading we can not customize equality ourselves, it's all determined by the algorithms defined by the language, which are very well explained here.