Announcing `async fn` and return-position `impl Trait` in traits

date: 2023-12-23 · Tags: #rust, #dev, #news

As I mentioned in my previous post, community is very interested and excited about async fn in traits.

In the end of year 2023, it finally happened: async fn in traits is now stable and released with version 1.75.0.

Refs:

Syntax Style in Python Pattern Matching

date: 2023-12-18 · Tags: #python, #dev

Some "corner" cases in Python pattern matching syntax:

match obj:
    case int(0): ...  # special case for 0
    case int(): ...   # any other int
    case float(): ... # any float
    case _:           # anything else
match obj:
    case int as i: ...   # can this work?
    case int(i): ...     # `i` will be `0` in the later context
    case int() as i: ... # any other example from official doc
    case _:              # anything else

I would prefer case int() as i over case int(i)?

Becase the later one feels like i is still unconverted to int yet?

An Example of Covariance, Contravariance and Invariance in Python Type Hints

date: 2023-12-12 · Tags: #python, #dev, #functional-programming

Qiangning Hong (@hongqn) share a Python type annotation tip on X (Twitter), and raised discussions about covariance, contravariance and invariance in Python

from collections.abc import Sequence

a: list[str] =["a"]

def f1(a: list[int | str]): pass
def f2(a: Sequence[int | str]): pass

f1(a)  # incompatible type assignment
f2(a)  # compatible

So why?

The key point is that list[int | str] is not covariant with list[str], while Sequence[int | str] is covariant with list[str].

The reason of Sequence is immutable and is also covariant, most immutable containers are covariant, so f2 cannot modify the list even if it is passed as a list.

List is mutable, so if the parameter is declared as a list type, list[str] and list[int | str] are two different types. In type system, mutable types usually are invariant (e.g. MutableSequence, list, set in Python).

It would be more clear that we add an function to accept Sequence type, and it will be compatible with variable a:

def f3(a: Sequence[str]): pass

f3(a)  # compatible

Refs:

Pointer as a Type or Different Roles of the Asterisk in Clang

date: 2023-12-02 · Tags: #clang, #functional-programming

Which style do you prefer to declare a variable in C?

  1. int *name
  2. int* name

Rasmus Andersson (@rsms) open a thread 1 in X to discuss the history of the convention of put asterisk symbol (*) (also known as unary operator) as a pointer type attched to the name (style 1) rather than the type (style 2).

Nowadays, after a few years of experience as a programmer, I prefer style 2. It's more practical and easier to read in the functional programming way.

There are also many quite interesting comments and supplementary materials in the thread about deferencing operator 234, historical choices 5 and personal flavor 6. Worth to dig in.

Only one critical warning to pick the second style

Avoid declaring more than one variable per statement! -- Phil Eaton (@eatonphil) 7

That means DO

int* foo;
int* bar;

and DO NOT

int* foo, bar;

Footnotes

  1. Origin thread from @rsms

  2. Comment from @rsms

  3. StackOverflow - How to explain C pointers (declaration vs. unary operators) to a beginner?

  4. Comments from @dpc_pw

  5. Bell Labs - The Development of the C Language

  6. Comment from @eatonphil

Why do Rust packages have any dependency on C code?

date: 2023-12-01 · Tags: #rust, #clang, #good-reading

Alexis King 1 is one of my most advocated programmers in PL community. She is doing great! 🥰

Here is a fun and informative answer 2 wrote by Alexis for Why do common Rust packages depend on C code?. So I just post it as a recommendation.

Basically, the TL;DR points are:

  • C ABIs
  • C is your operating system’s interface
  • C ABIs are difficult to separate from the C language
  • C ABIs are difficult to separate from C toolchains

Footnotes

  1. Tweet from @lexi_lambda

  2. StackOverflow - Why do common Rust packages depend on C code?