474 subscribers
6 photos
1 video
2 files
550 links
python, go, code quality, security, magic

Website and RSS:
https://itgram.orsinium.dev

Source:
https://github.com/orsinium/itgram

Author:
@orsinium
https://orsinium.dev/
Download Telegram
I've stumbled across the work of Ray Toal, and there is a lot to explore. I wish I had lectures like this in my university. Algorithms, data structures, databases, programming languages, security, networking, and much more.

I especially like Computer Language Semantics. He covers what is syntax, syntax design, and has good introductions to many languages with lots of examples (for example, to Clojure). Quite a good way to get started with a new language when you already know some programming. He also published a book Programming Language Explorations which, I think, is based on these courses. He published a ple GitHub repo for the book with examples of programs on each language he covers (and that's a lot of languages). Also, the book landing page links a few similar resources, like Syntax Across Languages, a big page that compares how the syntax for different things (like function call) looks like in different languages. And he also provides this overview page of different languages, with a short description, application examples, links, and tags.

But there is more cool stuff, I can't reasonably cover it in a single post. For example, this guide on clean code. Or intro to command line. As I said, a lot to uncover. I recommend you to go right to his home page and find yourself what resonates with you:
https://cs.lmu.edu/~ray/
πŸƒ go-recipes is a collection of Go snippets and tools to make different cool little things in Go: draw a dependency graph, prettify test coverage report, parallelize tests, show Go assembly, etc.

#golang
Aging programmer is a short list of random thought by a 40 y.o. engineer on what has changed for him over the years and what stayed the same.
πŸ”§ onefetch is a little tool to show some basic stats about a git repo: authors (and percent of code contributed), commits, lines of code, languages, size. And that's it, really. Not much, but it's quite easy to install and quick to run (Rust at its best), unlike some other alternatives I tried before.

#cli
πŸ”§ d2 is a CLI tool (written on Go) for generating diagrams from a text definition of what is related to what and how. If you know what is PlantUML, MermaidJS, or GraphViz, it's the same, but a bit friendlier. For example:

block1 -> block2: text on arrow
block2 -> block3
block4

If you want more examples, the authors maintain a text-to-diagram.com website that compares D2 to similar tools.

I tried it for a few projects, and that's what I'm going to use from now on for all diagrams. It's easy to install, has a nice syntax, and gives quite a nice output. There is no way to apply a custom style to group of elements (like class in CSS), but other than that it's fine. When you need custom colors or something, you still can do it on per-element basis.

#cli
πŸŽ₯ Make Illegal States Unrepresentable is a beginner-friendly talk about writing good type annotations. The speaker covers what is type safety and illegal states, why it matters, and shows three techniques how to achieve that. Examples are on Scala, but can be translated to Python, Rust, or TypeScript. Not to Go, sorry, no algebraic types and atoms for you.
Go 1.20 has been released! I'm most excited about the addition of profile-guided optimization (PGO). Now you can run on production a copy of your service with the profiler enabled, redirect there a small percent of users, export the collected profile, and recompile the service with -pgo=/path/to/profile. The compiler will use the information from the profile about which lines of code are executed more often and optimize the binary for them. More specifically, Go 1.20 compiler will do more aggressive inline for the hot parts, which adds 2-4% of performance on average. That's not much but it might be much more in the future versions of the compiler.

I always liked the idea of PGO. There were many blog posts about people moving around parts of code (and also many PRs into Go itself doing the same for stdlib) to get a better performance for the most often executed path. And it always bothered me as one of the things that the compiler should do instead of humans. Well, now it can!

More in the Go documentation: Profile-guided optimization.

#golang
A week ago, SQLAlchemy 2.0.0 was released. Now, the default way to describe ORM models is using declarative type-annotations based definitions. So, the fields instead of id = Column(Integer) can be described as just id: int. In some cases, it can get more verbose, but it pays back by better IDE integration, syntax highlighting, type checking, and other cool stuff that comes with type annotations.

I wanted to try different alternative ORMs with asyncio and typing support, but never got to it. Now I think that it gets quite hard to beat SQLAlchemy. The project, despite being very old, still keeps up the pace (what I can't say about Django ORM, Pony ORM, or Peewee) and has very good support for modern practice. Namely, for asyncio and type annotations.

Anyway, there are some asyncio-powered ORMs that I haven't tried but that look interesting:

+ sqlmodel is a thin wrapper on top of pydantic and sqlalchemy from the author of FastAPI. It's not actively maintained but there is not that much of code for it to be a big problem. This is the most popular ORM on this list because the author is famous.
+ ormar is another wrapper on top of pydantic and sqlalchemy to consider. Don't get deceived by the number of commits, though, they all are from dependabot.
+ tortoise-orm is an asyncio ORM inspired by Django ORM. At this point, I'm not sure anymore that it's a good idea. A long time ago, I used to like Django ORM for its similicity, but now I'm more skeptical about this simplicity as I learned how much of poor performance and testability it costs. Internally, it uses pypika for building the queries.
+ piccolo has quite a nice query builder but model definitions aren't declarative. Also, they say its "fully type annotated" but that's not what you might expect. There is Any all around, and no type safety at all in what the queries return.

#python
Hosting SQLite databases on Github Pages is a blog post about how to run SQLite on the frontend. SQLite gets compiled into WebAssembly and the author implemented a virtual FS (sql.js-httpvfs) that serves the database in chunks instead of downloading the whole database at once. Apparently, for it all to work well, you need either a small DB or good indices that allow to get all information needed without fetching the whole database.
πŸ“ Parse, don’t validate is another one good blog post about writing better type annotations. I short, instead of checking the correctness of values everywhere (or even worse, implicitly assuming they are valid), check them once, convert it into a new type, and then accept that type in every place where an already validated value is expected. For example, in Python:

from typing import NewType

Username = NewType('Username', str)

def parse_username(raw: str) -> Username:
...

And then all other functions that expect a valid type should be annotated with Username.

There is more in this blog post, with examples, corner-cases, and all that stuff, so I recommend to read it. The code examples are on Haskell, but they should be easy to understand (if you're not easily scared by monads) and the techniques can be translated to the language of your choice.
πŸ“ Golang is evil on shitty networks is another reminder that networking is messy. The blog post and the related GitHub issue got some traction, and there are answers to it on the orange site from Russ Cox (the author of the code in question) and John Nagle (the author of the algorithm). It all together is a very interesting reading on networking issues and how it is solved in TCP.
Matching on negative literals results in a parser error. This Github issue is a good example of why I will never touch Elm. Elm is a very interesting functional language but gosh the governance is bad. The bug report is that Elm explodes if you try to use negative numbers in pattern matching, and this is the answer of Elm author:

> Why are you doing this? Instead of fake examples, can you explain how this comes up?

D-uh. There was a drama a long time ago that Elm banned using JS directly in third-party libraries (reserving this possibility for stdlib only), and that decision caused many people to leave the language community. I'm surprised anyone even stayed.

I guess the point of this post is that when picking a programming language, not only the language itself matters but also the community and the governance around it.

The Go core team is considering adding telemetry in Go toolchain (compiler, formatter, linter, language server, all that stuff) that is opt-in by default. I wonder how far this story would go, but I think it will be fine. There already were talks that Go is just another Google's product, they don't care about community, and generics (the initial proposal based on contracts) are getting pushed. And that story the Go team managed well. They canceled the controversial proposals, and what we now have in Go is much more community-accepted.

I could also rant about the Go community itself (and push-back on generics for years as an idea), but I should stop somewhere.
πŸ“ Functional Programming in C++ is a (mirror of) blog post from John Carmack about using functional approach in, well, any OOP language, actually, not just C++. I like how well-thought, practical, and balanced his vision on this. He covers pure functions and immutability, their trade offs, and how to fit into the messy OOP world. I think it's a good intro into the world of functional programming, just enough to get interested and already start using it at work.
TLA+ is a formal specification language to describe design of distributed systems and then let the computer find issues with that design. The name stands for "Temporal Logic of Actions". "Logic" means that you mostly work with boolean values and operations (you also have sequences, numbers, sets, and functions, though). "Temporal" means you can describe how your system changes over time (something will eventually happen or something always happens). And finally "Actions" means that your system is described as a state machine of states and transitions between them.

It is designed by Leslie Lamport (he's not the one who made the IDE and verifier, though), the creator of LaTeX. Hence the syntax of TLA+ is basically LaTeX. It's designed for mathematicians rather than programmers, and so describing imperative operation in it is mind-bending. So, Lamport later also created PlusCal, an imperative DSL that generates TLA+ code. TBH, it's all a big mess and far cry from modern programming languages, their syntax, and conveniences, but it gets the job done.

The best place to learn TLA+ and PlusCal is learntla.com by Hillel Wayne, his blog, and his Practical TLA+ book. His materials have the benefit of being designed for engineers, rather than any math-heavy and obscure-symbols-loaded materials from Lamport. BTW, the book is dirt cheap, it almost feels like Hillel pays half of the production price for you. He himself says that he made learntla.com because he didn't like that his book costs money.

Don't worry about any materials being ever outdated, TLA+ doesn't get any updates for 9 years.
So, the story goes like this: I learned TLA+ to my best, but it doesn't sparkle joy. I never wanted to program on LaTeX, or ever touch LaTeX for anything, really. And then I discovered Alloy.

Alloy is a formal verification language (and IDE for it) for describing categories of entities, relations between them, and constraints between these relations. For example you can have category User with relation follows to the set of users, and a user cannot follow themselves. That's how you describe it in Alloy:

sig User {
follows: set User
}

fact no_self_follows {
no u: User.follows {
u in u.follows
}
}


That's it! There are shorter ways to describe the constraint, but this way is more similar to what you would do in Python. And, as you can see, it feels like a real programming language, and the syntax is quite nice.

When you describe your system, you can check different constraints on it (do the formal verification) or simply press "show" in IDE, and it will produce different graphs of the system that fits your description (with one and many follows, DAGs, loops, and so on).

It all doesn't seem like much, but, thanks to Curry-Howard correspondence, you can describe using it anything: types, sets, database records, servers, boolean logic, etc.

Alloy never was considered as an alternative to TLA+ because it didn't have temporal logic. But things have changed just a few years with introduction in Alloy 6 of even more cool temporal operators than TLA+ has. So, now I see Alloy 6 as a good replacement for TLA+ for myself that is developer-friendly, readable, more powerful, and easier to wrap my head around. Alloy does sparkle joy!

Learning resources:

+ Finding bugs without running or even looking at code (or Alloy for TLA+ users, it's the same talk for different audience) is a good intro video.
+ Alloy Documentation is an unofficial documentation by Hillel Wayne about Alloy. At the moment of writing, it’s not updated for Alloy 6, so skip the "time" section. The rest is good.
+ As for TLA+, check out the tag Alloy in Hillel Wayne's blog, it has some good posts. I especially recommend Formally Modeling Database Migrations (doesn’t use time) and Alloy 6: it’s about time (covers the new time syntax).
πŸ“ Microfeatures I'd like to see in more languages. I don't find most of the listed features useful, but it's interesting to see little quirks of some not so famous languages.
Stop Writing Dead Programs is a great talk about some legacy features that modern programming languages keep (and so we keep using them) from the times of punchcards.

I'd a bit argue with the ending, though. I believe in visual programming languages too but I think it's quite a big leap there from how we program now. Some people go all-in for visual languages, some say to always bet on text. I think the trick is to find the balance there, and the next big language is something like Node-RED (with visual representation of high-level flow and text representation of logic inside of each function) rather than Enso where everything is visualized. I'd like to see better structure and navigation for modules and functions, as it was in smalltalk, and more interactive development, as it was in lisp. The ideas aren't new, we just need to get them back into modern languages. I'm currently deceiving a plan to get Livebook (Jupyter but better and for Elixir) to that level πŸ€”
Raft: Understandable Distributed Consensus is amazingly clear, beautiful, and interactive visualization of how Raft algorithm works. Raft is the algorithm for picking a leader node and synchronizing changes across multiple nodes in a distributed system. This is the magic behind the replication of RabbitMQ, Nats, Etcd, CockroachDB, and many others.
πŸ“ How do One-Time passwords work? A nice little blog post with an example on Go.
πŸ“ INTERCAL, YAML, And Other Horrible Programming Languages. TL;DR: we have lots of bad DSLs that are YAML with control structures attached on top of that.

With each year, fewer and fewer people laugh when I say "YAML developer". I think there are several reasons why we have YAML everywhere.

One is that when you just start a project, YAML seems like a reasonable configuration solution. It's relatively readable and there are parsers for all languages. And then one day you need control structures, and instead of rewriting everything, you simply add on top of it a template engine you like and call it a day.

Another reason is marketing. If you take a DevOps or JS engineer and introduce a new fancy tool, it's easier to persuade them to pick it up if it's YAML than if it's Python or Clojure. Everyone knows that programming languages are hard and YAML is easy, right?

I think DSLs are even worse than YAML, though. At least with YAML you already have syntax highlighting, a code formatter, and a basic linter. Out of all Makefile, I strongly prefer Taskfile because I can work with it without learning a yet another poorly made syntax and installing yet another glitchy vscode extension.

If you need a powerful configuration language with control structures, reusability, and predefined variables, go pick Starlark (I posted about it in Russian here and here). Or simply make a Python library instead of yet another DSL interpreter. Python is installed almost everywhere, many engineers know it good enough, and it's quite readable, especially for simple cases. With Python you get a huge ecosystem, linters, type checkers, code formatters, and all that cool tooling. For example, I made docked Python library that generates Dockerfile, and I alone could provide safety features and IDE support that Dockerfile cannot dream of.