HNHacker News
TopNewBestAskShowJobs

linkdd

2,632 karma · joined June 19, 2019

email: david.jose.delassus@gmail.com

  - https://link-society.com
  - https://krouter.cloud
  - https://flowg.cloud
  - https://linkdd.github.io
  - https://david-delassus.medium.com
submissionscomments
linkdd··on I'm moving my projects off GitHub
Github existed long before they were bought out by Microsoft.

A company is run by people, with different opinions, when new people get in charge, the company changes as well. Microsoft is not hostile towards Linux and OSS and embraced it, deal with it.

linkdd··on I'm moving my projects off GitHub
Imagine a programming language with the YAML syntax. You get modern CI/CD.

Though, Gitlab CI is less powerful than Github Actions. With Gitlab CI, you can only have one pipeline per repository, and you have to play with conditional includes based on some CI variable to implement multiple pipelines.

While with Github Actions, you can simply have multiple workflows, listening to different kind of events (webhook, issues/pull requests events, ...)

linkdd··on I'm moving my projects off GitHub
I wonder what will happen when all those OSS forges ran by non-profit organizations will crumble under the load.

In the end, only for-profit businesses remain in the race, Gitlab, Github, Bitbucket, ...

linkdd··on How Long from AGI to ASI?
Better ask MULTIVAC.
linkdd··on Ask HN: Alternatives to Reddit
When talking about a business doing business, the concept of "evil" is non-sensical.

A business will do everything to stay profitable. That is the purpose of a business.

Any alternative to Reddit that gain some popularity is doomed to meet the same problems of scalability, infrastructure costs, and content moderation. Those things are not free, they cost money, therefore will be run by a business, doing business, trying to stay profitable, and will become "user hostile" once it is not profitable anymore.

This is the fate of any successful centralized social network.

linkdd··on Why not tell people to “simply” use pyenv, poetry or anaconda
How is `node_modules` different from `/path/to/venv/lib/python3.X/site-packages` ?

Are PyPI, cargo, Maven, etc... all immune to supply chain attacks?

linkdd··on Why not tell people to “simply” use pyenv, poetry or anaconda
Is the fact that there are multiple package managers for the same package fornat/spec the reason why people say it's a mess?

Genuine question: How is PyPI different from NPM, Maven, crates.io, etc..?

Why "Python packaging is a mess" and not the others?

linkdd··on Functional Python Programming
> I'm not into types [in Python]

In Python type hints are just that: hints.

mypy is a very poor static analyzer, and a lot of Python code (especially in frameworks like Django) is inherently dynamic and cannot be type-checked. And that's ok.

Though, documenting your API with type-hints really helps, especially with VSCode (via pyright) popovers when you hover a symbol/function.

linkdd··on Functional Python Programming
For tail recursion, you can use this snippet of code:

  class Recurse(Exception):
      def __init__(self, *args, **kwargs):
          self.args = args
          self.kwargs = kwargs
  
  class Terminate(Exception):
      def __init__(self, retval):
          self.retval = retval

  def tailrec(func):
      def wrapper(*args, **kwargs):
          while True:
              try:
                  func(*args, **kwargs)

              except Recurse as r:
                  args = r.args
                  kwargs = r.kwargs

              except Terminate as t:
                  return t.retval

      return wrapper

  @tailrec
  def fact(n, acc=1):
      if n == 0:
          raise Terminate(acc)

      else:
          raise Recurse(n - 1, acc * n)
Of course, it will be slow because it relies on exceptions :P
linkdd··on fe: A tiny, embeddable language implemented in ANSI C
"new" when talking about a repository with 15 commits, the last one being 3 years ago.

It is obviously a toy experiment and it took my 5s to realize that.

While it does not say "this is a lisp", it also does not say "this is a new shiny thing that will change the world". In fact, it says nothing except "look at what i did".

linkdd··on Crun: Fast and lightweight OCI runtime and C library for running containers
A chainsaw is not safe. But you can learn to use it safely.

Replace chainsaw with:

  - knife
  - guns
  - C programming language
There are tools and methods (and a lot of discipline) to ensure safety in C:

  - compiler's sanitizers[0]:
    - address: to detect out-of-bounds and use-after-free bugs
    - pointer-compare, pointer-subtract: to detect invalid operation when pointers are non null
    - shadow-call-stack: to detect return address overwrites (stack buffer overflows)
    - thread: to detect data races
    - leak: to detect memory leaks
    - undefined: to detect undefined behaviors
    - ...
  - static analysis tools, like Splint[1]
Would you ride a motorbike without the proper protections (helmet, heavy jacket, ...) ?

[0] - https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.h...

[1] - https://github.com/splintchecker/splint

linkdd··on Crun: Fast and lightweight OCI runtime and C library for running containers
You know sanitizers and static analysis tools exist, and have existed for decades, and have been the basis for the work done in Rust and other "safe" languages?

Also, a disciplined C programmer will always keep the size of the buffer near the buffer itself.

For example, using something like this is perfectly safe (though, we can see the performance hit of those if-statements if used intensively):

  struct buffer {
    size_t size;
    char *data;
  };

  void buffer_alloc(struct buffer *buf, size_t size) {
    if (buf != NULL) {
      buf->data = calloc(size, sizeof(char));
      if (buf->data != NULL) {
        buf->size = size;
      }
    }
  }

  void buffer_free(struct buffer *buf) {
    if (buf != NULL && buf->data != NULL) {
      free(buf->data);
      buf->size = 0;
    }
  }

  bool buffer_read(struct buffer buf, size_t offset, char *dest) {
    if (dest != NULL) {
      if (buf.data != NULL && offset >= 0 && offset < buf.size) {
        *dest = buf.data[offset];
        return true;
      }
    }

    return false;
  }

  int main() {
    struct buffer buf = {0};
    buffer_alloc(&buf, 123);
    char c;
    buffer_read(buf, 124, &c);
    buffer_free(&buf);
    return 0;
  }
It is possible to write safe C code, but it takes understanding of the language, sometimes of the compiler as well.

The whole "There is no programmer who don't make mistakes" argument is fallacious at best.

C is like a chainsaw, there are certain rules on how to use it safely. Yes you can cut limbs with a chainsaw, that does not make the chainsaw useless.

linkdd··on Crun: Fast and lightweight OCI runtime and C library for running containers
And there are more than 2 models of cars. The metaphor is still valid.
linkdd··on Crun: Fast and lightweight OCI runtime and C library for running containers
Take a car, the engine is the OCI runtime, crun, containerd, etc.. The whole car is Docker, or Podman. Kubernetes is the city where the cars run.

---

EDIT: For more details, OCI (Open Container Initiative) defines a few things:

  - an image format (how to create them)
  - a runtime specification (how to run them)
  - ...
A container runtime is an implementation of one of those things.

Docker is a set of tools hidden under a unified CLI which gives you the ability to:

  - create images
  - upload/download images to/from a registry
  - run images with volumes, networking configuration, environment variables, ...
But Docker is only one host.

Kubernetes is an interface to abstract a cluster of hosts. Everything is described as a "resource" which goes through the "control loop":

  1. the user uses the k8s REST API to create/read/update/delete the resource
  2. the k8s api server will contact admission controllers (via webhook) to authorize (and/or mutate) the action
  3. the action is persisted to a distributed database (usually, etcd)
  4. then, controllers are notified of the change and will run the side effects
This is the simplified version. But what is stored in the distributed database is called the "desired" state, and controllers have the duty of observing the real state (the "observed" state) and make it converge towards the "desired" state.

So a "Pod" controller's job will be to observe Docker instances, to check what containers are running, and start/stop the containers based on what "Pod" resources exists in k8s's database.

A "Deployment" controller's job will be to observe the "Pod" resources in the k8s database and create/update/delete them based on what "Deployment" resources exists in k8s's database.

etc...

In theory, Kubernetes does not need docker. You could have a "proxmox" controller which would start/stop virtual machines instead.

Kubernetes provides a lot of tooling for storage management, secret management, networking, workload management, etc... so that you can manage it all with a unified REST API.

The very nature of the "control loop" makes it very extensible, allowing you to build layers of abstraction on top of layers of abstraction on top of layers of abstraction ... A real "onion cloud" if I dare say it.

linkdd··on Sketch of a Post-ORM
ORMs (especially the Django ORM) fulfill 95% of my needs. For the 5%, I use raw SQL via the ORM's escape hatch (which Django and SQLAlchemy provides).

To be fair, my needs aren't that complex, I do mostly CRUD on database tables, most of the business logic is handled in my code, eventually wrapped in a `@transaction.atomic` (thank you Django).

If I need stored procedures, I'll add a Django migration which creates the said procedure with raw SQL.

If I need to manage the schema myself, I'll also make a Django migration with raw SQL, then I'll create Django unmanaged models.

For the portability across RDBMS, it's nice to have an SQLite database in the dev environment, so that the developer does not need to run a PostgreSQL instance (in docker or whatever). And for the test suite, I even use an in-memory SQLite database.

I do put my ORM queries in a specific module which provides a higher level API, I will have functions like `get_users_sent_invites` or `publish_article` etc... so that the rest of my code never sees database code. A function `get_user_by_id` will return the User model or None, and handle the ORM's potential exceptions to return meaningful errors to the business logic.

It also makes database access easier to test and benchmark. You might call this DAO or not, terms are irrelevant, it's just good practice to separate concerns IMHO.

linkdd··on Let's make a Teeny Tiny compiler (2020)
Higher level than assembly? Yes. High-level? No. Not with manual memory management, not without strings/encodings native support (char* is a bytestring, not a text string), not with so many platform-dependent features that are not abstracted away.
linkdd··on Let's make a Teeny Tiny compiler (2020)
> A program that doesn't emit at least VM bytecode should not be called a compiler, but rather a transpiler.

https://en.wikipedia.org/wiki/Compiler

> In computing, a compiler is a computer program that translates computer code written in one programming language (the source language) into another language (the target language).

> The name "compiler" is primarily used for programs that translate source code from a high-level programming language to a low-level programming language (e.g. assembly language, object code, or machine code) to create an executable program.

> a program that translates between high-level languages, usually called a source-to-source compiler or transpile

Since when is C a high-level language?

There is no need to be so pedantic. A transpiler is a special kind of compiler.

linkdd··on SectorC: A C Compiler in 512 bytes
https://www.youtube.com/watch?v=WLwTlC1R2sY -- How slow is Javascript really? Javascript vs C++ (Data Structures & Optimization)
linkdd··on SectorC: A C Compiler in 512 bytes
An interpreter with a JIT compiler is able to do more optimizations because it has the runtime context to make decisions, while a AOT (ahead of time) compiler will not know anything about what happens at runtime.

This is why some JIT'd languages (like Javascript) can be sometimes faster than C.

linkdd··on Ask HN: What's your favorite software testing framework and why?
> you end up with very long, repetitive scenarios or vague scenarios. Or even both.

Almost correct :D

The BDD scenarii also act as "user stories" in a Scrum/Agile workflow. It was a nice way to re-use what the product owner requested.

linkdd··on Ask HN: What's your favorite software testing framework and why?
> I created StrictYAML, which this tool uses, because of it

I'll look more closely into it then :)

> Gherkin is awful at that.

When I use BDD, it's because I'm handed down scenarii written by non-tech people. And it's always in the Gherkin format, then I chose the right Gherkin engine for the right tech stack. That might be cucumber, or another.

linkdd··on Ask HN: What's your favorite software testing framework and why?
Thank you. Your library seems nice.

Unfortunately, I have to say it... I hate YAML with a passion, k8s, github actions/gitlab ci, ansible, etc... When I'm doing ops jobs, I feel like I'm coding in YAML.

Btw, this hate for YAML birthed https://linkdd.github.io/tricorder/ :P

linkdd··on Ask HN: What's your favorite software testing framework and why?
I love pytest, and use it with Hypothesis[0] for property based testing. I also enjoy using pytest-bdd[1]

[0] - https://hypothesis.readthedocs.io/en/latest/

[1] - https://github.com/pytest-dev/pytest-bdd

linkdd··on Writing Python like it's Rust
So you deny that the industry used Python to build serious production softwares?

Understood, no need to argue then, I don't think any amount of proof would change your mind...

linkdd··on Writing Python like it's Rust
Type hints communicate intents. They can be used for many things.

Django-Ninja use them to do dependency injection and generate schemas for your API (using pydantic). autodoc use them to generate the documentation of your function. etc...

It does not replace duck typing, proof here: https://peps.python.org/pep-0544/

linkdd··on Astmaker – A DSL in Rust for programming language designers
You can express the same idea in english and german and french and ...

But if you try to invent your own language (like Tolkien did), you are not "expressing an idea" (aka: speaking), you are creating a framework to express ideas.

When you write a program, you follow a grammar to express an idea (the solution to the problem you are tackling). When you design a programming language, you are creating that grammar (using another language to implement it afterwards).

Also, here "programming language designers" designates "people who are working on their own programming language". Those are the people I'm talking to when writing this Rust crate and blog article. The webdev doing CRUD microservices could not care less about astmaker.

linkdd··on Stop Saying C/C++
Speaking of Cessna, `{ Foo * c = a + b; }` could be a valid implementation of flight simulator.
linkdd··on Astmaker – A DSL in Rust for programming language designers
As a non-paying member (or anonymous visitor) you get to read 2 "member-only" articles per month.

For "member-only" articles, you get a remuneration proportional to the "member reading time". For members who subscribed via your "onboarding" page (I don't have one I think, I don't know, I should look into it), you get a remuneration proportional to their reading time on any articles, not just yours.

The friend-tag on an article's link removes the paywall, allowing you to increase views when sharing the article. The more views your article has, the more Medium will promote it. But many platforms removes it as it may have trackers associated to it (I haven't looked into that to confirm or infirm).

EDIT: Fun fact, the Javascript subreddit even forbids medium links because they consider the content to be spammy 99% of the time.

For Medium, they want to incite people to buy a subscription, hence the paywall. But they also want writers to generate the content for them, hence the friend-link and remuneration model.

The remuneration is quite small, so I don't think they are loosing money. But short clickbaity articles about how console.log works can generate a LOT of views, and writers spamming those can earn up to 300$/month (or maybe more), hence the bad reputation of Medium. I'm not interested in doing that, I mainly write to share about my work and just enjoy the small remuneration as a reward for my open-source work: it's not entirely useless if I can get a meal per month out of it ^^

EDIT: Out of transparency, by writing an average of 1-2 articles/month on topics I enjoy, I managed to make an average of 10-15$/month. The ones about Rust are the more profitable ones, go figure :P

linkdd··on Astmaker – A DSL in Rust for programming language designers
> Though personally I think writing LISP interpreters with parser libraries should be considered sacrilege

Agreed, though the point of the article was to explore the Rust ecosystem. When learning, a little bit of blasphemy isn't a bad thing :)

linkdd··on Astmaker – A DSL in Rust for programming language designers
> Rust seems to be good for language designers thanks to a combination of features

Not only the type system is quite nice, the ecosystem is full of nice crates:

  - lexing: logos
  - parsers: rust-peg / lalrpop / nom
  - utilities: string-interner / linecol / snailquote
I also wrote about this here: https://david-delassus.medium.com/writing-a-simple-lisp-inte... (friend link, no paywall)
← PreviousPage 5 of 29Next →