Author here, thank you for having this project on the front page! I want to explain why this bot is in C, while, for instance, another project of mine that implements a LoRa driver/protocol for the ESP32 (a much lower level project, in theory) is in Python!
This code started as the Telegram bot Stonky, it's on Github, and you'll see the bot does a lot of financial analysis things, including Montecarlo simulations. I really needed the speed. Later my daughter was diagnosed with scoliosis, and requires to wear a corset. To take track of the time she wears it was a pita, so I wrote another bot (not released so far) and put it in our family channel.
Then... I needed another bot. And I finally extracted the common parts from the two. So:
1. For Stonky, speed was essential, but not for my next bot.
2. Once I needed to write the new bot for the corset I tried the Python lib. And... I started to have the first code compatibility issues (accross versions) of the modern software stack (context here: https://twitter.com/antirez/status/1726305869032570992).
3. Meanwhile Stocky was no longer able to work because I did the unescapable error of basing it on the Yahoo Finance API, now retired :( So I told myself, I don't want to relay on a software stack that will make this bot unable to work or obsolete in 2/3 years because all the libraries will change fast (and, if you check, you will see there was a lot of work that went into Stonky back in the couple of weeks when I worked at it constantly).
On top of that, with Stonky I decided to serve each request with a thread, and not in multiplexing. In the specific case of a Telegram bot this is basically able to simplify many things: many bot requests are long living, because you want to call an LLM API, or Whisper to transcribe, or do a Montecarlo simulation on a stock history, (btw the Whisper thing will be one of the official examples of this library) and so forth. Now in Stonky this approach worked so well because it's written in C, so each thread consumes only minimaul resources associated with the OS thread creation.
Finally: With SDS lib, my JSON and Sqlite3 wrapper (the wrappers are the interesting part of the project IMHO) it is not so different than writing Python code. So, I said, why not?
P.S. this library is just a work in progress, hacked while I'm doing many other stuff. I hope it will improve in the next weeks. I use Telegram for more than 10 years now, with all my friends and family. So it is very likely I'll require to write more bots in the future :D
Unrelated: I just want to say thank you for all of your amazing work over the years. You’re a software hero of mine. I’m 100% certain your code and work has saved me time, money, and maybe even my job at one point! Also, sorry to hear about your daughter. I’m going to pray for you and your family! (If my memory serves me right, you don’t believe in God, but I hope you don’t mind.)
Thank you Jay! It's a great thing to read in the morning :) Appreciated. I don't believe in God, but in a very "soft" way, that is, I'm happy other people enjoy their religious life.
Because certain hn users will dogpile on that when they have nothing to add to the discussion. Cue the same person trolling why not c++, same person saying how it would be done in D, and cue various people talking about rust and unsafe.
Amazing project, and sorry to hear about your daughter. I wore a back brace from age 4 until ~10, when my scoliosis curvature took a turn for the worse. They did surgery on me back then (27-28 years ago now) and put a stainless steel (or titanium im not sure) rod on my spine and fused it. I've been stuck at 5'1" since age 11, and have had to deal with some teasing about my height, but otherwise I've been able to have a good career in software and tech.
If you want to reach out and ask me any questions about life with scoliosis (or anything else for that matter), feel free to reach out to me:
Your project is pretty cool...I can see myself integrating IRC support so I can bridge communications between telegram and IRC. I already do a lot of bot-like stuff using Sopel (Python) and notify (golang), but love working in C/C++.
If, by bullet point 2, you are talking about python-telegram-bot, not only is it like that... the owners are also absolute shitheads about it - if you ask for help while using an older version of their library in their support chat, they threaten to ban you.
Yes, I have this vibe about many library authors in the Python/Ruby/Javascript ecosystem at this point. I don't want to be part of that, nor as a user, nor as a coder.
The Thompson story is very telling about C and how semantically powerful it is. KT tried to rewrite UNIX in B at some time, but he failed. Assembly allows you to do many interesting things because it is a low level language, and yet you can build abstractions, so it was a better language than B to write UNIX. But once B got structures, and was starting to become C, things changed. Structures with fields and pointers to other structures is the ha-ha moment of C. It is what really makes the whole language so special. With this simple building block you can start building abstractions that are able to abstract away low level details, while, at the same time, you have full control on low level details.
Do you see any features in modern, high-level programming languages (such as Python, Go, C#) that could guide the next evolutionary step for C, without sacrificing that low-level control?
Knowing KT worked on Go, I'd guess he'd say concurrency, but that's difficult to get right without sacrificing low-level control. What's your take?
Sure, C could be much better right now. In some incredible way people that are able to drive the future of C made all the worst choices, undermining the language instead of improving it, for most parts (with undefined behaviours).
C just needs:
1. A solid and modern standard library, with basic data structures, sane strings, higher level sockets, ...
2. A very simple object system. No inheritance, no advanced features at all, just the ability to call object->method(1,2,3) and getting a 'self' reference.
3. Ability to perform operations on function exit in order to clean-up locally allocated things. So as I allocate things or open files and alike, I can specify some cleanup code doing things like if (fp) fclose(fp); that is executed when the function returns in any case.
I read a paper 'What If We Don’t Pop the Stack? The Return of
2nd-Class Values' where they discuss their research into delaying popping the stack to allow functions to return data allocated on the stack. As a small brained embedded primate that doesn't use malloc that sort of thing would make C vastly easier to use.
If C hadn't been standardized by ISO, I wonder if C implementors would have eventually added stuff like this just because they found it useful.
Or if C had been standardized, but C++ didn't exist, maybe they would have added features like this simply because contemporary languages like Object Pascal and Ada 95 supported object oriented programming better in practice.
There are other OOP paradigms, no need to force 'this' pointers on everyone like C++ does. Both 2 and 3 could be done with semantic-aware macros instead.
I believe the C++ way would be the right thing for C. Note that this does not mean in any way to inherit all the stuff from C++, nor even constructors and stuff like that. Simply a way to avoid doing this:
list_add(&mylist,1);
But instead:
mylist->add(1);
Note that doing this is not an option:
mylist->class->add(&mylist,1);
It's not just ugly (even if often used), but also uses an additional pointer, which in some application (like Redis) is a no-go because of memory usage.
Perhaps, though I think one should be careful, as reproducing C++ in this fashion runs awfully close to reproducing what I see as C++'s largest sin...
Let me explain, I feel iteration speed is of utmost importance. So C++'s mistake of mixing interface and implementation (data layout specifically) leads to massive include bloat, and ultimately contributes significantly to the compilation time problem in C++. In contrast, in C, functions are almost entirely decoupled from structure data layout, and implementation, this promoting much more svelte headers and reduced compilation time for many projects.
So, IMO, it would be important to seperate object interface, from the layout, or risk a major, if not the most major, advantage of using C over C++
> Structures with fields and pointers to other structures is the ha-ha moment of C. It is what really makes the whole language so special
How is it special at all?
> you have full control on low level details.
Yeah, if you add random attributes to the language and control the compiler. C still can’t properly do vector instructions, while even Java can, but so can C#, Rust, C++. It’s simply not a low-level language.
Did you check out the clang vector extensions? And before "but that's not standard C!": in the C world, the interesting stuff happens outside the standard in language extensions, the standard is mostly irrelevant for real world code. What counts is what specific compilers have to offer.
To the point that Linux, probably the most important C project in the world, was written in the GCC dialect for many many years. I think it's no longer the case.
AFAIK the only reason why Linux compiles on Clang now too is because Clang tries to emulate GCC behaviour as closely as possible? I doubt that the Linux kernel would compile out of the box with Microsoft's C compiler for instance ;)
This code started as the Telegram bot Stonky, it's on Github, and you'll see the bot does a lot of financial analysis things, including Montecarlo simulations. I really needed the speed. Later my daughter was diagnosed with scoliosis, and requires to wear a corset. To take track of the time she wears it was a pita, so I wrote another bot (not released so far) and put it in our family channel.
Then... I needed another bot. And I finally extracted the common parts from the two. So:
1. For Stonky, speed was essential, but not for my next bot.
2. Once I needed to write the new bot for the corset I tried the Python lib. And... I started to have the first code compatibility issues (accross versions) of the modern software stack (context here: https://twitter.com/antirez/status/1726305869032570992).
3. Meanwhile Stocky was no longer able to work because I did the unescapable error of basing it on the Yahoo Finance API, now retired :( So I told myself, I don't want to relay on a software stack that will make this bot unable to work or obsolete in 2/3 years because all the libraries will change fast (and, if you check, you will see there was a lot of work that went into Stonky back in the couple of weeks when I worked at it constantly).
On top of that, with Stonky I decided to serve each request with a thread, and not in multiplexing. In the specific case of a Telegram bot this is basically able to simplify many things: many bot requests are long living, because you want to call an LLM API, or Whisper to transcribe, or do a Montecarlo simulation on a stock history, (btw the Whisper thing will be one of the official examples of this library) and so forth. Now in Stonky this approach worked so well because it's written in C, so each thread consumes only minimaul resources associated with the OS thread creation.
Finally: With SDS lib, my JSON and Sqlite3 wrapper (the wrappers are the interesting part of the project IMHO) it is not so different than writing Python code. So, I said, why not?
P.S. this library is just a work in progress, hacked while I'm doing many other stuff. I hope it will improve in the next weeks. I use Telegram for more than 10 years now, with all my friends and family. So it is very likely I'll require to write more bots in the future :D