It’s been a joy to work with it! The standard library for working with strings, JSON, YAML and XML is top notch. Type safe and extremely fast, very important characteristics for a licensing server that is queried hundreds of times a second.
I used the super simple Kemal HTTP server library which I like for APIs where most of the logic happens on the backend.
I have 8 years of experience as a Python developer and 5 as a Swift developer but after all that time I still like the terseness and type inference of Crystal.
one downside for me is the development speed, compile time is definitely noticeable if you come from an interpreted language
After ~10 years with Ruby, I decided to try out Crystal for my latest weird hobby project (a modern style bbs) and I have enjoyed it so much!
Considering the relatively short lifespan of Crystal, I was positively surpriced how good the documentation was and how fast, easy and stable the language it already is :)
Every language that gets a little creative will have these features that you probably never saw, have no idea what to do with them and when is a best practice to use them.
Things like fibers, or the ways to do iteration without a for-loop, or the do…end closure syntax. They’re new and weird for non-Ruby devs, but they have their advantages, and you just have to try and use them a few times and they’ll become as common as your previous language.
1) Would you consider open sourcing the licensing server in Crystal? 2) What's your revenue with Lunar? :)
Thanks!
Last month I’ve also found out about Keygen (https://keygen.sh/) which has a really nice offering, and I would have probably chosen it instead of building my own solution if I’d known about it. I’m concerned about uptime with my own solution, I don’t have the means to provide enough redundancy in case of a network or data center failure.
2. I’m earning about $3.5k per month on Lunar Pro licenses (on average, some months can be 5-6k, some 2k). Doing quality macOS apps is a nice market to be in. You get to do tools for your own usage and also share them with others for some side revenue.
I’ve also created The low-tech guys (https://lowtechguys.com/) and each new app published there is also bringing about $200-$600 per month.
Little by little, I’m hoping to get to a continuous revenue of $8k per month so I can build a home for my family and have more time to pursue my other hobbies (woodworking: https://reddit.com/r/DIY/comments/t1l4rk/_/hyhvjix/?context=...) and (instrumental music: https://soundcloud.app.goo.gl/Dv8AT2JgNWrzFtLa8)
I would say 3500 a month is even a median salary for an IT position in WE. From your resume I take it you still work full time? I wonder if that's even worth it at this point unless you make a lot more from your FTE position.
Anyway props!
I’ve written about how I quit my job in March last year and started turning Lunar into a revenue generating project here: https://alinpanaitiu.com/blog/journey-to-ddc-on-m1-macs/
There’s a lot more info in the article that you might not be interested in though. For the 1 year anniversary of this decision I’m writing another article with everything I tried with Lunar and other apps in the last year. That might be more relevant because I’ll share user stats, real numbers on revenue, trial and error with paid advertising etc.
Yes, $3.5k sounds pretty good for Eastern Europe, but the truth is that prices have also skyrocketed. I’ve been trying to get away from my current matchbox sized rented apartment and build a house with my wife. I’ve reached the conclusion that I need like $200k in savings to do it and I’m nowhere near that.
Sure, dealing with the problems of less knowledgeable users is sometimes annoying, because 99% of the problems stem from non-compliant monitors/hubs/docks etc.
But nowadays I get weeks at a time where I can do 0 work on Lunar and dive into my own curiosities (that's how I got to the idea of lowtechguys.com), or simply go on multi-city long trips with my bike without thinking that I have to ask for time off from a boss.
I don't look forward to being forced into long video calls where my time is simply wasted so that higher-ups can hear me saying "we're working on it".
The ROI is much higher than you think, time is far more valuable than money.
Also curious -- from your OP re: Crystal:
> It’s been a joy to work with it! The standard library for working with strings, JSON, YAML and XML is top notch. Type safe and extremely fast, very important characteristics for a licensing server that is queried hundreds of times a second.
You said you're doing ~$3.5k/mo in licenses for Lunar. Where's the licensing volume coming from here? Keygen handles licensing for hundreds of products and millions of devices and I very rarely hit 100 RPS even on a busy day, so kind of curious how your licensing is setup to produce that much volume. :)
I’m already looking into using Keygen for my next non-AppStore app. I’ll definitely reach out if I have any concern. Although from what I saw, your site explains everything well, and the dev tier will be helpful in testing.
I’m not getting 100 RPS constantly. It happens rarely, mostly when releasing updates. When an update is detected, Lunar has to check if the period of free updates hasn’t ended. Then the server is contacted again when the new version is launched.
With 3000 pro users (some received licenses for free because they donated when Lunar was free), 100 RPS can happen for short bursts and the server has to cope well with this even if it happens rarely.
But I really miss some of Crystal’s features in other languages I work with:
1. Being able to declare union types when ingesting some not-so-normalized data
alias UserID = String | Int32 | UUID
2. Macros and meta-programmingFor example here I have a `storedprop` macro which I can use to define propertied that get saved automatically to a YAML config when they are changed: https://f.lunar.fyi/uRW69B/settings.cr
class Settings
include YAML::Serializable
storedprop host : String = "ddcutil-server.local"
storedprop port : UInt16 = 3485
end
The good thing is you’re not really required to learn this stuff if you don’t want. But they surely can make the language fit to your style better if you invest the time to understand them.From what I've seen, Pharo has a few things that would make Bret Victor proud. But it's still early days for me, I'm still getting the hang of the language.
And while the language is obscure there seems to be at least one SaaS company that is hiring for remote European software engineers [2]. There are some other examples, but IMO [2] seems to be the best one among all the examples [3].
[0] https://pharo.org/features
[1] I know that niche languages can have very weird issues, but there are enough side projects where these issues won't be much of an issue.
That and the lack of a vim editing mode (sorry, but I find it very hard to write code in an editor without vim style bindings, even though I don't use vim itself most of the time), make it a pretty painful experience.
In general, while Smalltalk the environment is a great idea, I think its UI could use some improvements and be much more keyboard driven.
Also, namespaces/modules please.
Though, I've been looking through Calypso a bit (the window browser) and for me it seems really difficult to add anything at the moment. If it gets any easier, I'll create some tutorials.
Loading in your own code to append to an image is doable via a .bashrc style mechanism. As in, you put your code in a file, open a playground and load it in, and your image is appended.
I wouldn't call Pharo OOP.
I'd call Pharo live OOP.
Normally, objects in languages are asleep like a bear in hibernation or something only to wake up when spring arrives (or when you click "compile"). But in Pharo they are awake when you edit them. If I was a DJ/producer, I'd try to see if it makes sense as a music tool.
Coincidentally, seems my post have been the top #1 post on the Arc forums since I first made it, ~17 days ago. That forum could do with a bit more of traffic :)
Because during work I tend to be very pragmatic, and choose pretty boring, but battle tested technology. For the projects I have been working so far, usually niche tech doesn't provide enough tangible benefits to justify the risk of choosing it, the generally smaller ecosystem, less tooling, fewer documentation and potentially longer developer onboarding. Doesn't mean only the most established things one can choose, but avoiding things that are too new and unknown or too far off of what I'm comfortable working with.
And once a tech stack is chosen you are likely not going to change it significantly for years to come. So it can get a little stale and I can get an urge to try new things. But my warm fuzzy feelings or curiosity for some new tech doesn't justify increasing complexity by adding no stuff to a production product/service.
literally a decision I made on a side project a few weeks ago.
That exact idea has been tingling through my mind for a while. I did some experiments, but Prolog (and anything logic programming, really) is a bit of a pain to integrate nicely with Python, which is what I'm building my system with.
I'm looking to make things declarative as much as possible, but having Prolog manage the automation rules would be next level. I imagine it abstracts away a lot of the boilerplate and unnecessary implementation details.
On the Prolog side of things with not that much framework code here is a trivial example:
message(['Smarthome','Notify','brain','ping'],_):- publish(['Smarthome', 'Notify', 'brain', 'ping_response']).
This code receives a MQTT message with a topic of Smarthome/Notify/brain/ping ignoring the message body and then publishes a return message on topic Smarthome/Notify/brain/ping_response
I even have a container that runs nothing but cron with a mqtt client installed that sends mqtt messages at various times of the day and all Prolog has to do is subscribe to those topics and handle those messages.
Look in the examples directory for some basic pub/sub code.
The Prolog code that runs in my house is pretty specific to my house so I figured the best way to open source things would be as a framework more than an implementation. You can contact me via issues on the github repo and prod me into adding some more advanced examples - I've learned a lot since my last commit on the repo.
I've started using the Redis functionality recently added to SWI-Prolog, so my code now responds to MQTT messages and uses state queried from Redis to help determine what actions (implemented by sent MQTT messages) to send out. The beauty is that since I don't do anything that blocks significantly in the Prolog code it is now single threaded - even the MQTT listening. It still responds quickly enough and is MUCH easier to deal with than multi-threaded.
An example of what I'm doing is I built a bunch of ESP8266/EESP32 display devices that control neopixels/OLED/LCD displays. When one of those devices boots it sends a MQTT message announcing its location and capabilities (display type, bit depth, dimensions). Prolog receives that message and then stores that info in Redis. So that device info is all dynamic.
So then later Prolog might get a notification that something is in the driveway. All by MQTT it requests an image from the appropriate camera, then sends the image off to Sighthound and deepstack image recognition servers. The Sighthound front end sends a message back to Prolog with a description of any vehicle spotted which Prolog then matches against known vehicles. If it determines for example that a Fedex truck is in the driveway then Prolog sends notifications around the house - it queries all the display devices from Redis and then based on the capabilities of each devices creates a JSON formatted MQTT message to send to each announcing the Fedex truck. It then also sends a MQTT message to some Java code that connects with Google and sends a push message to an Android app I wrote that displays the alert on my phone and watch.
Before I switched to MQTT I was using Prolog with CORBA as the message transport and back then I also had Visual Basic and MS Agent as part of the system. One night I got bored and a little while later had 3 Peedy the Parrot characters singing Row Your Boat in a round across three different computers coordinated by Prolog. It was actually only a page worth of custom Prolog code for that.
I started learning Nim a few years ago, and came back to it last year after seeing it had improved in a number of areas. I started working on a practical utility, a self-contained document uploader system that could be customized for certain departments at work. Eg, take a Word document, convert it to PDF, upload to a specific location on our company website. Not truly a hobby project, but no one asked me for it, just playing with an idea I came up with based on frequent help desk tickets I get. I guess one of my hobbies is inventing programs that someone might find useful, without having an actual target audience. 8]
Since then I have written a handful of graphics programs in Nim which are more in my hobby area. I wrote a nice version of the Reaction Diffusion simulation that generates fascinating tile patterns and naturalistic forms. I also plan to make a version of Pickover popcorn.
More recently I started working with the V programming language and have been playing with the Mandelbrot example they provide. I added a 256-color palette, higher iteration options for more detailed images, and am working on a system to create a catalog of favorite points and images. It will also save and load simple text files describing a particular point and zoom level that people could share in a chat or text message. This kind of thing has all been done before, but these are just exercises in fundamental aspects of the language to help me learn the basics and determine if it's worth pursuing it further.
I am playing with these languages particularly because they make smallish executable programs that can be easily distributed. I'm working up to developing simple GUI CRUDs with them to see how practical the process is. I'm still looking for something that will replace what I used to do with Delphi.
The first time, after several years of working with Python, I missed the dynamic data structures like lists and dictionaries. Open arrays work pretty well, but Pascal still requires a lot of overhead to set things up compared to `d = {}`.
The next time I got a bit further with it, but I remember everything being just slightly different enough that I had to dig for examples and documentation to do simple things I used to do easily in Delphi. I think I got some of my old graphics programs working but there was enough friction that I lost interest and moved on.
But its worth giving it another shot since I have a lot of old Pascal code I'd like to play with again, and knowing about these difficulties going in I might do a better job next time.
What I like about Nim is the terse syntax similar to Python, and the more dynamic data structures like sequence, but also the typing similar to Pascal and the compiling to executable thanks to C. I like the V language too for its batteries-included nature, but haven't gotten far enough with it yet to tell if I will stick with it. The docs are a good start, but they only have Discord for a community and that is hard to work with.
It leaves ample opportunities to do something in a niche way. I am often disenchanted after reading many open-source, ostensibly high-quality c++ libraries — namely Apple’s WebKit and a few parts of Google’s Filament. That said, there are a few gems of c++ that I can’t describe as anything but archetypally niche.
Nlohhman’s JSON library (also, the constexpr fork of that library), and the CTRE library for compile time regular expressions are absolute gems.
Also, I interpreted the parent comment as talking about the implementation/architecture of the projects, not the projects themselves.
That’s neat about C++ templates too which is why I drew the comparison.
Personally I think Lisp macros are considerably more readable than C++ templates, especially when it comes to errors, but I’m happy to agree that reasonable minds may differ on that.
9 years later Go is not such a niche language. Rclone is doing ok too :-)
(If this is easy with other compiled languages, let me know. Maybe gcc?)
My excuse is to create a rules based expert system for tabletop games to help game masters not have to remember as many rules during battles and such, but it is definitely slow going since I only hobby program when I'm procrastinating revising whatever writing project I'm on.
(Or when I'm procrastinating by typing on HN)
Erlang has been my favorite for over a decade. Feels like its own operating system: spawn many processes, kill/pause them, send/receive messages async no problem, add service introspection. It feels kubernetes/microservices architecture way before its time, except without the cgroups constraints or language options :o). Downside is slow text parsing, number crunching, no efficient vectors
Whereas racket looks steered mainly by the academic group working on it, with some attention shifting to the new Rhombus project https://github.com/racket/rhombus-prototype
These days everything looks like it's using json/yaml and trying to add logic/constraints to it to make it declarative, either through logic controllers (eg kubernetes operators) or by embedding it in the syntax, eg terraform HCL, declarative UI frameworks.
Scheme DSLs are a good alternative and could be used to generate code or glue between the components you use.
For day job I code in high level languages like: javascript/typescript, python, and back in the day: ruby, perl, and php. Never was comfortable in C/C++ but always wanted to get more proficient. And felt like to be honest programmer, I need to know a systems language.
Lately I've been learning Zig https://ziglang.org/ and I'm quite happy with the developer experience, despite it's only at version 0. It's kind of a whole new world I didn't think even possible: C level performance, but with great ergonomics and just basically: it's fun to develop in! Like C, but fun and safe(er).
I think Clojure's niche-ness is a hidden strength as well, as the community is so strong and knowledgeable that you get very good help when you need it, from all angles. It's been a pleasure to use Clojure and interact with the community, even though the language is effectively built by one person instead of a committee (which, I think is another one of Clojure's strength [but not so hidden]).
I'm convinced statically typed functional languages are significantly more productive.
I got a Haskell job and don't even have a degree.
Sometimes the language ends up really growing. I did that with Elixir very early on, and now Elixir is a solid choice for new dev even for a company. It's still a little bit niche, but I think it's just at the beginning of major growth. Frameworks like Phoenix and Nerves already make it great, but with first-class machine learning libraries coming and LiveBook, it's headed toward being seriously attractive even for later adopters.
Using different programming languages is mind expanding.
The other language I really like to work in is Elixir. I use it for hobby projects where the concurrency model fits really well.
So.. why wouldn't you code a small hobby project in something niche? That's more than half the fun.
There is also the aspect, that many only learn some mainstream language and do not look further. This in turn limits what is used in many workplaces. It is simply people not further exploring and educating themselves. I do not say, that they have to do that in their free time, but I myself, in my free time, do not want to be limited by mainstream choices, like I would be in most places at work.
I also need new interesting things in my software life. The ordinary stuff bores me. I try to learn more things. There are many things to learn from niche or at least non-mainstream languages.
Wrote a lot of fancy packet captures in that language.
Most favorite capture was Quantum where some unknown source tried to hijack one of my TCP connections, and Zeek caught it and reported it … dutifully.
[1] https://github.com/tromp/ChessPositionRanking
[2] https://github.com/tromp/ChessPositionRanking/blob/main/src/...
I love Haxe for its power and the number of targets it can deploy to, but it doesn't do anything for my career unless I want to work as a game dev (which I don't).
So, I'm leaning more into Python with mpypy (and mypyc for iOS) and trying to focus more on the problem domain rather than the programming language.
So for hobby projects where nobody else can tell me what to do, I still use one of the two, regardless of how dated they tend to be perceived.
Go is a pleasure to work with, however, so I’m exercising that more and more.
I loved VB for a long time but finally moved away from it after the VB 6.0 years, primarily because my daily driver switched to Linux and I stopped writing software for windows. I now use a Mac but I tinker with Linux. My family has so much trouble with Windows I’m very unlikely to ever try it again and it’s been 23 years anyway.
Rust, Swift, Modern CMake, Vulkan, WebGL, Hugo and Gatsby are examples of things I've used in side projects that have directly benefit my professional career.
The main reason I do it though is simply because it's fun to see new and different things. I'm very much a programming language and frameworks/libraries tourist. Of the languages I've tried, F# comes closest to seeming like it could be good for general use, if only it was more popular and had a killer framework or application space (like Scala for Spark). I think it gets overlooked because of its MS/.NET origin and OCaml folks either don't care for it or are small in number.
Jack is a language that you create on your own in the Nand2Tetris course. In this project, I first followed the course to build -- assembler, VM translator, compiler and operating system.
Once I finished the course, I decided to build my own CPU emulator so that the whole computing stack is built by me from scratch. Then I decided to change some specifications and also add userland applications to go beyond the course. For example, I have built a chip8 emulator in Jack.
Just curious: what’s your niche language called?
The language is Decl. I think at this point it's more a notation than a language; it relies on a host language for execution. My understanding of what I set out to do has evolved over time, and the past couple of years I've thought of it more as a DSL along the lines of SQL (not in that it's used for database access, for which we already have SQL; I just mean that it's used by embedding it in something else that defines actions).
Also, does it count if I'm writing a niche language as my side project? :-) Check out EndBASIC (https://www.endbasic.dev/) if curious.
Some of the new languages survive and mature, like Go and Rust. Eventually, those become the new Java or C++. Some will fade away.
I still think Elixir/Phoenix/LiveView are great technologies, but I don't think they offer me anything professionally that the current stuff doesn't; at least not for my use cases.
There was an opportunity cost to making the switch too, and I feel like that was a poor use of time.
I think a lot of people hate it because it feels like cheating in some way. AI researchers like going the long route. Some people refuse to believe AI is as good as it is. Some attribute human-like qualities like humor to it.
But I don't really care for all that. I just enjoy spending time with it.
I recently learned rust while experimenting with a neural net architecture. The neural net was mixed, the rust knowledge is pretty useful.
I.. don't love it. I often am using the ! operater to say "yes, I'm sure there will be an object here" in an array and having to get too particular with type specification (i.e. for keys in a map). I'm not sure it adds all that much value to my project.
The problem is, you have this language which offers you a million handy little tricks which seem very useful for all kinds of little niche problems. The boring and common sense approach would be not to use them, because it would give your colleagues too many headaches to figure out what they are and why you chose to use them. But in practice the temptation is often too strong.
The focus should be on the core abstractions like Functor, Monad, Monoid, Applicative, etc that are sound, non-leaky, universal abstractions that are useful for all kinds of little niche problems.
> The boring and common sense approach would be not to use them, because it would give your colleagues too many headaches to figure out what they are and why you chose to use them. But in practice the temptation is often too strong.
The boring Haskell approach you describe should include taking advantage of those core abstractions.
If your coworkers don't get them, they should learn the core abstractions and how to use them.
I like to code in Haskell because it works better than any other language I’ve tried — also for larger projects. Where by “works better” I mean that I’m able to deduce what a piece of code does just by reading it more easily than for any other language I’ve tried.
I think it’s the combination of pure functions and strong types that enables this, but I’m not entirely sure.
For a niche-enough language you might contribute in this way even if you didn't start it.
It's pleasant to write stuff in a non-ugly language, while still having access to the JS environment if you need it.
Think of hybrid Pascal + Python, pretty nice standard library, can be compiled into an executable.
As much as I admire functional programming, my brain still mostly think in procedural.