472 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
A few years ago, I made a Go library genesis with some generic functions, mostly inspired by Elixir. And now, Go 1.18 beta is available, and it has proper generics! The 1.18 release is already in a few months. I used this opportunity to try the generics and migrate the project. And it's pretty cool (except one stack overflow but it will be fixed in the release). If you want to read more about the project history, I've made a short reddit post. So, give genesis a try, it's pretty cool now.

#golang
About a year ago, I played a bit with writing a programming language. That's quite a fun journey. If you want to go that way, there are a few helpful links:

+ pls-lab.org — quite a big wiki with PL-related theory.
+ proglangdesign.net/wiki — useful links, resources, and reading list about writing PLs.
+ Mapping High Level Constructs to LLVM IR — long unmaintained but still helpful collection of tricks for LLVM.
+ How I wrote my own "proper" programming language — a series of articles about writing a programming language on C++ targeting LLVM.

As the compiler language I had chosen Python because it's pretty good for fast prototyping and there is no need to care about compilation performance (nobody's going to use your language anyway).

As the compilation target I had picked LLVM, it is low-level enough to give interesting challenges but not too low-level. Also, LLVM is better than FIRM, WASM, Go AST, and similar just because it has more documentation, tutorials, even books. However, the documentation is for smart people and mostly for C++, I didn't get anything helpful from it.

There are the libraries I was using for my compiler:

+ lark is great for writing parsers.
+ llvmlite is good enough for generating LLVM code, nothing better is there for Python anyway.

If you want to use another language for the compiler (especially a functional one) without a good parsing library, I'd go with a parser combinator. Serious languages don't use it because of a bad performance and picking a random interpretation in case of an ambiguity. But if you just want to have fun, who cares.
By accident, I dropped everything from my phone. Not in the first time, to be said. it made me think that I need 2 things:
1. "Infra as a code" for all applications.
2. rsync for photos.

Today we'll talk about the first one. In particular, about automating installation of apps on an android phone. I made for myself a few simple Python scripts that iterate over hardcoded app IDs and call the following tools:

+ bloatware can be removed by adb (probably, no root required, IDK). Show installed apps: adb shell pm list packages. Remove a specific app: adb shell pm uninstall -k --user 0 com.android.chrome.
+ fdroidcl allows to install apps from F-Droid.
+ Not everything is available on F-Droid, though. I often install such apps from 4pda (a Russian forum with apks, both official and modified ones) but there is no CLI for it. You can manually download the files and then install them using adb install ./file.apk.
+ You definitely shouldn't install bank apps from random people on Russian forums. So, for some apps you still need Google Play. For that, I use gplaycli but it took me a while to make it work, including fighting with 2FA and fixing some bits of the code.
Font Awesome 6.0.0 is released. Font Awesome is a pretty cool collection of web icons, packed as a font and used through a CSS file that adds a class for each icon. For example, this is how you can add a Python icon:

<i class="fa-brands fa-python"></i>


(or "fab" instead of "fa-brands" in older versions or if you want to save a few bytes)

There are many alternatives, like icomoon, that allow you to generate your own small font instead of bringing on the prod thousands of icons you will never use. But, apparently, Font Awesome is just easier to use. Like, who cares if your blog downloads 10 Kb or 130 Kb font, nobody visits it anyway.

On the negative side, a few years ago they started to require registration to get the CDN URL. But don't worry, I got you covered:

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v6.0.0/css/all.css" integrity="sha384-3B6NwesSXE7YJlcLI9RpRqGf2p/EgVH8BgoKTaUrmKNDkHPStTQ3EyoYjCGXaOTS" crossorigin="anonymous">


To upgrade, just replace the version number and then regenerate the integrity hash:

curl https://use.fontawesome.com/releases/v6.0.0/css/all.css | openssl dgst -sha384 -binary | openssl base64 -A
GitHub has added math support in markdown. Now, you have even fewer excuses to write your own blog engine instead of writing actual blog posts. It always has been my advice to just go with plain GitHub for your first blog. I mean, it has git, ability to contribute, discussions, nice rendering, navigation (file tree), categories (directories), emojis, analytics, and whatever else you might wish for. And all of that with zero configuration.

The math support isn't perfect yet, though. You can find some issues outlined in Math on GitHub: The Good, the Bad and the Ugly. I personally can't say much. I have only one article with math in it (Normalized compression distance), and it seems to be perfectly rendered. People always will find some corner-cases when something isn't as good as LaTeX, so don't overthink it.
code.golf is a challenge for writing a simple program in as few characters as possible. For example, for _ in range(10): pass will turn into for _ in [0]*10:0. Beautiful, isn't it? I feel like it's the best resource for preparation for interviews. Make them question your sanity! I managed to hit 59 bytes for Fizz Buzz on Python which puts me on 16th place. I think it deserves a spot in my CV.

Recently, they've added support for Elixir. And I should say, it's much harder to make something awfully short on it comparing to Python. Well, partially because I'm less skilled in it, yes, but also because it's more demanding. Empty string is falsy in Python but not in Elixir. Spaces are required in some places in Elixir for readability but in Python the parser tries to be as forgiving as possible. End there is "do-end" for blocks, of course. My best result for Fizz Buzz on Elixir is 125 bytes.

Unsurprisingly, the top 3 shortest solutions for Fizz Buzz are on K and J which are array languages. And then goes Raku which is rebranded Perl.
On /r/datascience, there recently was a discussion "Why are companies willing to spend so much on hiring new employees but on retaining them?". And the top reply is pretty good. I thought I know the answer but this reply showed me a new perspective. Highly recommend:
https://www.reddit.com/r/datascience/comments/uo589a/comment/i8cut6w/

> Because HR departments are self-serving and they generally ignore the value of productivity, knowledge, or performance in order to highlight the cost savings generated by their strategies.

Sometimes I feel like the whole IT industry (or the whole capitalism, let's go big, just look at the current stock market) is pretty bizzare and consists of bad decisions caused by one-sided effectiveness metrics.
fasterthanli.me is a relatively popular blog dedicated to comparing how better Rust is than Go. Well, it's a personal blog of a guy, so it's not dedicated to anything in particular, but feels like this is the main theme for most of the posts. Even if it's about just Rust, comparison with Go will pop up. For example:

+ Lies we tell ourselves to keep using Golang
+ Some mistakes Rust doesn't catch
+ I want off Mr. Golang's Wild Ride
+ Aiming for correctness with types

And you know what? Being an engineer who loves Go and avoids Rust, I agree with most of the things (if not all of them, I don't keep the score). The type system in Go sometimes is too forgiving and even the existing type system could've been used better in stdlib.

A good example (that is also covered in the blog) is having string as the type for filesystem paths. It prompts so many bugs, from messing the argument order to concatenating paths as they were just, well, regular strings. And all of it could've been solved just by having type Path string declaration. What's interesting, there is a time.Duration type which does exactly this. Instead of passing time in seconds (Python, C) or microseconds (Erlang, Elixir) and messing with it each time, you explicitly specify the units when building the type. For example, 5 * time.Second. Just beautiful and much safer.

So, when you write anything on a language with a type checker (in the modern world, it's almost every language), I urge you to create subtypes for things and don't just use strings and integers. It's not so hard and it makes the code so much safer and more readable.

Oh, and I recommend reading this blog, even if you don't care about Rust or code correctness.

#golang #rust
httpstatuses.io is a cheat sheet with HTTP status codes. I wish it were just in man pages by default like ASCII characters table (try typing man ascii and you'll see what I mean). Maybe, I can send a feature request int httpstatuses.io repo to return something CLI-friendly when requesting a page from cURL.
One of the best things in Elixir is it's metaprogramming capabilities. You can write pretty performant DSLs (domain-specific languages). That means, you can naturally write on another simple language (HTML, SQL, XML, protobuf) inside of Elixir. Maybe, with a bit different syntax but the same semantics. There are some of my favorite DSLs:

+ Ecto is the best ORM I ever worked with. If you used to active record approach, you'll might feel uncomfortable at first, then you'll question why there is some repetition, but when you come through this, you'll see how ingenious are some design ideas in Ecto. Inside, it has a separate module for migrations, for schemas, for queries, for data validation, for database connection. Each module is independent and can be used on its own, but it also plays together very well. And each module has a nice and very natural DSL. For example, if you know SQL, you already can read this query:

Ecto.Query.from(p in MyApp.User, where: p.last_name == "Smith") |> MyApp.Repo.all

+ In most of the languages, when you write tests, you write functions or calsses, inside all dome magic fundtions or methods to assert something... But not in Elixir. In Elixir, you have ExUnit which is so natural way to write tests. For example:

describe "get_user_role"
test "the first user is always admin" do
assert get_user_role(1) == :admin
end
end

+ The same for HTTP endpoints. Usually, you have functions which you register later (or decorate) for expected HTTP methods and paths. In Plug, you kinda just do what you need right away:

get "/hello" do
send_resp(conn, 200, "world")
end

forward "/users", to: UsersRouter

+ Temple is a DSL for HTML. Which is, again, very natural if you know HTML (but less repetitive):

temple do
h2 do: "todos"

ul class: "list" do
for item <- @items do
li class: "item" do
div do: item
end
end
end
end

The elephant in the room is that in Temple you still have all these soup of end's at the end instead of closing tags. Python-style blocks are easier to read but in Elixir you have Ruby-style do-end. The motivation is that because of macros and all that stuff the parser needs to be able to recognize code block without knowing the context. For example, in Python, if is always a test expression and then a block to execute (which can be on the same line as any other block but it's still a block). In elixir, if is just a macro (a function) in which you pass do-end block as the second argument.

+ Re is my first Elixir library, a DSL for regular expressions:

Re.one_or_more(Re.Chars.any_digit) |> Re.compile

#elixir
Learn You Some Erlang for Great Good is the best way to learn Erlang. It's targeted at people who already know a programming language (any) and want to learn more about FP and Erlang. The author really wants to understand it all. There is a separate huge chapter on recursion and thinking recursively, with lots of detailed examples. And the whole book is in the same manner: detailed, with examples, and real-world use cases. It goes from very basic syntax to standard library, concurrency patterns and solutions, testing, distribution and so on. If you ever got interested in Erlang, definitely start there.

Now, about Erlang as a language. Why would you learn it nowadays? Well, the language itself is a bit messy, the syntax is old and alienating, static type checking is bad (and so go-to-definition will often just shrug at you), and there are not so many vacancies for it. However, underneath it is hidden a gem:

+ The best concurrency, distribution, and error handling.
+ Ability to deploy a service that will be running for 40 years without any downtime and will never interrupt a single connection,
+ Painless horizontal scaling until you have servers for it.
+ No bug will ever make everything explode and will never go unnoticed.
+ The best observability.
+ Debugging right on production without any performance degradation.

This is why Elixir appeared. Elixir is a language that provides on top of it a friendly syntax, great metaprogramming, modern package management, logging, some additional distribution primitives. But underneath it lives Erlang and all the same patterns and behaviors.

So, it's worth learning Elixir if you know the pain of distributed systems and want a tool that solves it. And it's worth learning Erlang to know better how Elixir works inside.

#erlang #elixir
Let's talk about type checking of Elixir. No-no, it's no a channel about Elixir yet but I still want to write down some of the research I do in the language.

+ Dialyzer is an Erlang type checker. It's very forgiving and so not so helpful as most of other type checkers in other languages. You can read more about it in Type Specifications and Erlang section of "Learn you some Erlang". For Elixir, it is integrated in Elixir language server and also available as dialyxir convenience wrapper.
+ Gradualizer is a new type checker for Erlang, more strict and gradual. It's still in Alpha but looks promising. For Elixir, it's available as gradient.
+ TypeCheck is an Elixir library to check types at runtime.

#elixir
The 3 Skills That Completely Change Your Social Life:

1. A good listener doesn't listen to respond. They listen to learn.
2. You don’t just listen to respond. You listen to understand. You go deeper.
3. How to never run out of things to say (I can't summarize this one in one sentence).
Maybe you should do less 'work':

1. You should try and figure out what expectations your colleagues and managers have of you. And also what you expect of yourself.
2. If you can meet these expectations in fewer hours than you are supposed to work, then you shouldn't just find more to do. Instead you should do something different.
typesplainer is a fun little tool (CLI, vscode/vim extension, and website) for explaining type annotations in a Python code in plain English. I think it has a pretty limited application (if you don't know a specific type, better read the official docs). still, might be helpful if you're starting on a project with type annotations but haven't worked with them before.

#python
Relatively recently, bloomberg open-sourced memray — the first memory profiler for Python that doesn't suck. I especially like their pytest plugin. I tried it and it works pretty nicely, it already found a few places in my code where memory consumption can be a bit less aggressive.

If you need to profile execution time, py-spy is still the best.

#python
awesome-bugs is a collection of articles about non-trivial bugs. It has such classic anecdotes as "Open Office Won't Print on Tuesdays" and "We Can't Send Email Farther Than 500 Miles" but also goes beyond that. Fun reading. It misses some famous ones, though, like Therac-25 scanner story, "the deadliest bug".
noclip.website is "a digital museum of video game levels". It contains levels from different games from different platforms rendered online with WebGL. Very interesting. For instance, now I know that the mirror floor in "Hotel Ocean View" from GTA Vice City is, in fact, a half-transparent floor containing a mirrored copy of the room below. Mirrors in most of videogames is a lie.
In Elixir community, there are a lot of talks about PETAL stack for dynamic websites. It stands for Phoenix, Elixir, Tailwind CSS, Alpine.js, and LiveView. The order of components doesn't make sense (except making it sound cool), so I'll cover them out of order:

+ Elixir is a functional programming language that has out-of-the-box scalability, hot reload, and other cool features that each big project needs.

+ Phoenix for elixir is like Ruby on Rails for Ruby. The default web framework. Big, powerful, and popular. Even if you write a very simple and small Elixir web app, you're likely to still use Phoenix for some of the conveniences inside.

+ LiveView is now part of Phoenix. And this is a huge game changer in web development. If you know PHP, it's similar to LiveWire. It allows you to have dynamic web pages where all content is rendered on the server side. LiveView will take care of sending data in both directions through websocket and make sure everything is stable and accounts for tons of corner-cases. At the end of the day, you will have a modern reactive website without writing a line of JS.

+ Alpine.js is for cases when you still need a bit of JS for some frontend-only logic. It's a micro framework. With LiveView, you don't really need React or anything huge like this because LiveView provides you with all nice logic, state management, components, and all that stuff. And alpine.js covers the rest. I used it for filters on my personal website and it works well. Well, it eats too much resources which is noticeable on a phone but it was easy and fun to code. So, I guess, worth it.

+ Tailwind CSS is a controversial one. It's basically CSS in your classes. When I need something low-level, I use CSS. When I need something high-level which takes care of nice defaults and adaptivity, I use bootstrap. And when I mix bootstrap with some custom CSS, I get all the same things that Tailwind CSS promises but with less boilerplate. IDK, I just don't understand yet what Tailwind tries to solve.

Someone even made petal_components Elixir library which contains Phoenix and LiveView components on top of Tailwind CSS and Alpine.js.

#elixir #web #js
verifier is a package that makes your Go code a bit nicer when you need to validate multiple things before running a block of code.

verify := verifier.New()
verify.That(transfer != nil, "transfer can't be nil")
verify.That(person != nil, "person can't be nil")
if verify.GetError() != nil {
return nil, verify.GetError()
}

They don't say it, but this is, basically, a monad. The package exists because Go doesn't have exceptions or powerful enough type system 👀 Anyway, the library is pretty helpful, remember it when you next time need to validate a lot of things.

#golang
Drunk Post: Things I've learned as a Sr Engineer. That's better than you might expect from the title.