Captain's log, stardate [-26]6280.00

This week in review: Moveit! system design

~more>

🔗 Advantages of Pattern Matching

I was discussing with a friend earlier today about the need for pattern matching and I remembered this particular blog that I read few years ago.

  • Pattern matches can act upon ints, floats, strings and other types as well as objects. Method dispatch requires an object.
  • Pattern matches can act upon several different values simultaneously: parallel pattern matching. Method dispatch is limited to the single this case in mainstream languages. -Patterns can be nested, allowing dispatch over trees of arbitrary depth. Method dispatch is limited to the non-nested case.
  • Or-patterns allow subpatterns to be shared. Method dispatch only allows sharing when methods are from classes that happen to share a base class. Otherwise you must manually factor out the commonality into a separate member (giving it a name) and then manually insert calls from all appropriate places to this superfluous function.
  • Pattern matching provides exhaustiveness and redundancy checking which catches many errors and is particularly useful when types evolve during development. Object orientation provides exhaustiveness checking (interface implementations must implement all members) but not redundancy checking.
  • Non-trivial parallel pattern matches are optimized for you by the F# compiler. Method dispatch does not convey enough information to the compiler’s optimizer so comparable performance can only be achieved in other mainstream languages by painstakingly optimizing the decision tree by hand, resulting in unmaintainable code.
  • Active patterns allow you to inject custom dispatch semantics.

Rust vs F#

Many years ago, back when I was interested compiler design, I briefly worked on F# in an academic setting. I am not sure if anyone uses F# in production but it is a very interesting langauage. I learned a lot about Hindley-Milner type inference, monads, pattern matching and more. Surprisingly I learned about functional programming features from F#.

I recently got more serious about learning rust and have noticed a lot of similarities between the two languages. One major difference is F# is garbage collected (because of C# base). F# is also a lot more forgiving than rust imo.

How to fix _wait_for_tstate_lock

If we ever try to exit server with objects in the Multiprocessing Queue, we could end up in a race condition that causes a deadlock with _wait_for_tstate_lock. One way to avoid it is to clear the queue before exit.

Debugging

To figure out which queue is not empty,

import multiprocessing
import inspect

# initialize a queue
q = multiprocessing.Queue(10)

# get function where the queue is created or where we are adding objects to queue
# so that we can identify which queue it is
caller = inspect.getframeinfo(inspect.stack()[1][0])
thread_name = f"MultiQueue_{caller.filename}:{caller.lineno}"

# add new object
q.put("hello")

# set thread name
q._thread.name = thread_name

QueueFeederThread is stared after you put an object into the queue. After the first time you put an object into the queue, you can set a name to the thread. You can then use py-spy to figure out which thread is preventing your program from exiting.

py-spy dump -p <pid>

References

Page 2 of 19