I think it's worse. The US market feels like a casino to me right now and grift is at an all time high. We're not getting good economic data, it's super unpredictable, and private equity is a disaster waiting to happen IMO. For sure there are smart people able to make money on the gamble, but it's not my jam.
I don't tend to benefit from my predictions as things always take longer to unfold than I think they will, but I'm beyond bearish at present. I'd rather play blackjack.
I’m on ghostty but warp is a lot more than a terminal. I used to consider their product to be a shitty AI powered terminal until I saw a demo of it. Now I consider it as a fair AI agent application that has a good CLI integration and some notebook features.
The growing popularity of ghostty has made me realize a lot of people don’t use scroll back history search. I use it frequently to save time and avoid having to rerun time intensive tasks to pipe them through grep or tee everything to a file.
I like Ghostty, but it's still missing a few features I need. Warp was interesting, but it was honestly overwhelming when I was simply reaching for a terminal. For now, I'm back on Terminal.app until Ghostty catches up feature wise.
You meant "iTerm2 with no scrollbars and no scrollback history search" was spelled wrong.
(yes I know they are working on it; but I also know iTerm2 and Konsole have had them since about forever, and I use that feature a lot, so it's kinda major impediment)
Just started using this - it's pretty nice. Very customizable but it makes my oh-my-zsh setup look like crap with it's fonts.
I started using it since it's cross platform and I use chezmoi, but the config quickly gets complicated if you want things like folders in your tab titles, etc
In Python this is a magical special case, but in Icon/Unicon it falls out somewhat naturally from the language semantics; comparisons don't return Boolean values, but rather fail (returning no value) or succeed (returning a usually unused value which is chosen to be, IIRC, the right-hand operand).
And in SQL you have
`x-coordinate` between `lower-bound` - 1 and `upper-bound` + 1
If you start programming in it though, syntax only matters during the first day. Familiarity comes very fast, and if you do five programming exercises, maybe one a day, 'implement a hash map', 'make a small game', etc. you will have no problems whatsoever once the week is done.
If you have a course where one day you're supposed to do Haskell and another Erlang, and another LISP, and another Prolog, and there's only one exercise in each language, then you're obviously going to have to waste a lot of time on syntax, but that's never a situation you encounter while actually programming.
This is far from true in my experience. I'm no Lisp hater (I wrote a self-compiling compiler in Scheme) but different syntaxes have dramatically different degrees of familiarity, like Latin letters and Cyrillic. How long do you think it would take you to learn to read phonetically in Cyrillic as fast as you do in the Latin script? It takes the humans months or years, if they ever arrive. But, also, some notations are more usable than others, even for experts, just as with other kinds of user interfaces. Flat is better than nested, simple is better than complex, complex is better than complicated, Perl and MUMPS are unnecessarily error-prone, etc.
I shouldn't have mentioned LISP because I don't use it and I actually find the parentheses to be annoying, but it's a paradigm and you need them. Cyrillic at full speed is obviously weeks. But Erlang is very math-notation-y and when I introduced people to some Erlang code I'd written they understood it once I'd given a presentation on it and were then able to do similar things.
I write way more algol-derived language code than ML, yet piped operations being an option over either constant dot operators where every function returns the answer or itself depending on the context or inside out code is beautiful in a way that I've never felt about my C#/C++/etc code. And even Lisp can do that style with arrow macros that exist in at least CL and Clojure (dunno about Racket/other schemes).
> Most people didn't think we were anywhere close to LLM's five years ago.
That's very ambiguous. "Most people" don't know most things. If we're talking about people that have been working in the industry though, my understanding is that the concept of our modern day LLMs aren't magical at all. In fact, the idea has been around for quite a while. The breakthroughs in processing power and networking (data) were the hold up. The result definitely feels magical to "most people" though for sure. Right now we're "iterating" right?
I'm not sure anyone really see's a clear path to AGI if what we're actually talking about is the singularity. There are a lot of unknown unknowns right?
AGI is a poorly defined concept because intelligence is a poorly defined concept. Everyone knows what intelligence is... until we attempt to agree on a common definition.
Not sure what history you're suggesting I check? I've been following NLP for decades. Sure, neural nets have been around for many decades. Deep learning in this century. But the explosive success of what LLM's can do now came as a huge surprise. Transformers date to just 2017, and the idea that they would be this successful just with throwing gargantuan amounts of data and processing at them -- this was not a common viewpoint. So I stand by the main point of my original comment, except I did just now edit it to say 10 years ago rather than 5... the point is, it really did seem to come out of nowhere.
Clippy at least had the courtesy of only blocking the bottom right of the window, these ridiculous Gemini pop-ups appear next to whatever cell you have selected and block things like column headers or values that you actually want to look at while editing the formula/value. It's insane to me that this was ever allowed to get deployed without a rational human being calling out the obvious issue.
Honestly I think it's the database that makes devs insecure. The stakes are high and you usually want PITR and regular backups even for low traffic apps. Having a "simple" turnkey service for this that can run in any environment (dedicated, VPS, colo, etc.) would be huge.
I think this is partly responsible for the increased popularity of sqlite as a backend. It's super simple and lightstream for recovery isn't that complicated.
Most apps don't need 5 9s, but they do care about losing data. Eliminate the possibility of losing data, without paying tons of $ to also eliminate potential outages, and you'll get a lot of customers.
Some thoughts so far: Installing gleam installed about 50 packages on my system (possibly all erlang/elixir related). But what if I just wanted to transpile to js? Perhaps this is a packaging issue on my system though.
What I really wish is that Lua would be considered as another transpilation target. I think gleam could shine for DSLs in other programs but embedding Lua is 3x easier than embedding a js runtime imo.
In general, I find the nicest thing so far the community. And I want to say that the quality of libraries and resources in the gleam community seems exceptionally high. It reminds me of the rust community insofar as that for most hard problems someone smarter than me has already worked on it and published a good solution (e.g. lustre, squirrel).
Then I would say you can also expect a lot of creativity and experimentation, the things that may fly under the radar in larger language ecosystems stand out here due to the growing and welcoming community.
> Perhaps this is a packaging issue on my system though.
Gleam is only officially distributed via the releases on GitHub [1] so if you pick up Gleam from a package manager that's always maintained by someone else. I think most of those community distributions do include Erlang and bits which is probably what pulled in all those extra packages!
In general, I found starting with a Erlang/Elixir framework tutorial helps. Phoenix includes a generic wrapper on top of PostgreSQL (Ecto provides data mapping and language integrated query), and hit a surprising number of users per host with trivial code (common game engine back-end.)
The only foot-gun I would initially avoid, is a fussy fault-tolerant multi-host cluster deployment. Check out RabbitMQ package maintainers, as those guys certainly offer a fantastic resource for students ( https://www.rabbitmq.com/docs/which-erlang .)
In my opinion, Elixir and Phoenix will give you a better experience with BEAM and OTP, excellent tooling, a more mature ecosystem, and one of the best web frameworks ever to exist. I think Gleam is cool, but I can't see trading these benefits in for static typing.
To be fair, I can't think of anything I care less about than static typing, so please keep that in mind when entertaining my opinion.
I also preferred dynamic typing, until my complex rails app grew to the point I didn't dare to do any refactoring.
But I didn't switch opinion until I discovered ML type systems, which really allow for fearless refactoring. At occasion there's some battling to satisfy the typesystem, but even with that I'm more productive once the app grows in complexity.
I thought I'd share my experience, not trying to convince anyone ; - )
My path is a little different. I have used Haskell, and I'm looking to get into OTP.
My original plan was either Elixir or vanilla Erlang depending on which one suits my sensibilities better. Reading about Gleam recently has me super, super excited. That's definitely going to be my path now.
I don't know if Gleam is the best entry into the world of rich types that you find in a language like Haskell--I'm yet to actually build something with it.
What I can tell you is that Haskell is a complete joy to use and it honestly ruins most other programming for me. So as a direction, I cannot recommend it enough, and I'm hoping, for my sake and yours, that Gleam offers a similarly stimulating sandbox.
Just a warning that it will take time to get used to "higher-kinded" types. It's an exercise in head scratching and frustration at first. The reward part arrives when you start thinking in types yourself and you know which ones to reach for and when you find the libraries you want by entering a signature on Hoogle.
I have a F# background, and thought to have read that some constructs I learned to appreciate are not available in Gleam (the one I can think of right now is currying, but I thought there were others).
The issue isn't that OTP isn't a priority for Gleam, but rather that it doesn't work with the static typing Gleam is implementing. This is why they've had to reimplement their own OTP functionality in gleam_otp. Even then, gleam_otp has some limitations, like being unable to support all of OTP's messages, named processes, etc. gleam_otp is also considered experimental at this point.
Having Erlang-style OTP support (for the most part) is very doable, I've written my own OTP layer instead of the pretty shoddy stuff Gleam ships with. It's not really that challenging of a problem and you can get stuff like typed processes (`Pid(message_type)`, i.e. we can only send `message_type` messages to this process), etc. out of it very easily.
This idea that static typing is such a massive issue for OTP style servers and messaging is a very persistent myth, to be honest; I've created thin layers on top of OTP for both `purerl` (PureScript compiled to Erlang) and Gleam that end up with both type-safe interfaces (we can only send the right messages to the processes) and are type-safe internally (we can only write the process in a type-safe way based on its state and message types).
I wholeheartedly agree with you that gleam_otp is janky. Still, actor message passing is only part of the picture. Here are some issues that make static typing difficult in OTP:
• OTP processes communicate via the actor model by sending messages of any type. Each actor is responsible for pattern-matching the incoming message and handling it (or not) based on its type. To implement static typing, you need to know at compile time what type of message an actor can receive, what type it will send back, and how to verify this at compile time.
• OTP's GenServer behaviour uses callbacks that can return various types, depending on runtime conditions. Static typing would require that you predefine all return types for all callbacks, handle type-safe state management, and provide compile-time guarantees when handling these myriad types.
• OTP supervisors manage child processes dynamically, which could be of any type. To implement static typing, you would need to know and define the types of all supervised processes, know how they are going to interact with each other, and implement type-safe restart strategies for each type.
These and other design roadblocks may be why Gleam chose to implement primitives, like statically typed actors, instead of GenServer, GenStage, GenEvent, and other specialized OTP behaviours, full supervisor functionality, DynamicSupervisor, and OTP's Registry, Agent, Task, etc.
OTP and BEAM are Erlang and Elixir's killer features, and have been battle-tested in some of the most demanding environments for decades. I can't see the logic in ditching them or cobbling together a lesser, unproven version of them to gain something as mundane as static typing.
EDIT: I completely missed the word "actor" as the second word in my second sentence, so I added it.
I suppose I was unclear. It is OTP-style `gen_server` processes that I'm talking about.
> OTP processes communicate via the actor model by sending messages of any type. Each actor is responsible for pattern-matching the incoming message and handling it (or not) based on its type. To implement static typing, you need to know at compile time what type of message an actor can receive, what type it will send back, and how to verify this at compile time.
This is trivial, your `start` function can simply take a function that says which type of message you can receive. Better yet, you split it up in `handle_cast` (which has a well known set of valid return values, you type that as `incomingCastType -> gen_server.CastReturn`) and deal with the rest with interface functions just as you would in normal Erlang usage (i.e. `get_user_preferences(user_preference_process_pid) -> UserPreferences` at the top level of the server).
Here is an example of a process I threw together having never used Gleam before. The underlying `gen_server` library is my own as well, as well as the FFI code (Erlang code) that backs it. My point with posting this is mostly that all of the parts of the server, i.e. what you define what you define a server, are type safe in the type of way that people claim is somehow hard:
It's not nearly as big of an issue as people make it out to be; most of the expected behaviors are exactly that: `behaviour`s, and they're not nearly as dynamic as people make them seem. Gleam itself maps custom types very cleanly to tagged tuples (`ThingHere("hello")` maps to `{thing_here, <<"hello">>}`, and so on) so there is no real big issue with mapping a lot of the known and useful return types and so on.
I read the code but I'm not sure I understood all of it (I'm familiar with Elixir, not with Gleam).
For normal matters I do believe that your approach works but (start returns the pid of the server, right?) what is it going to happen if something, probably a module written in Elixir or Erlang that wants to prove a point, sends a message of an unsupported type to that pid? I don't think the compiler can prevent that. It's going to crash at runtime or have to handle the unmatched type and return a not implemented sort of error.
It's similar to static typing a JSON API, then receiving an odd message from the server or from the client, because the remote party cannot be controlled.
> [...] start returns the pid of the server, right?
Yes, `start` is the part you would stick in a supervision tree, essentially. We start the server so that it can be reached later with the interface functions.
> [...] probably a module written in Elixir or Erlang that wants to prove a point, sends a message of an unsupported type to that pid? I don't think the compiler can prevent that. It's going to crash at runtime or have to handle the unmatched type and return a not implemented sort of error.
Yes, this is already the default behavior of a `gen_server` and is fine, IMO. As a general guideline I would advise against trying to fix errors caused by type-unsafe languages; there is no productive (i.e. long-term fruitful) way to fix a fundamentally unsafe interface (Erlang/Elixir code), the best recourse you have is to write as much code you can in the safe one instead.
Erlang, in Gleam code, is essentially a layer where you put the code that does the fundamentals and then you use the foreign function interface (FFI) to tell Gleam that those functions can be called with so and so types, and it does the type checking. This means that once you travel into Erlang code all bets are off. It's really no different to saying that a certain C function can call assembly code.
As someone who comes from Haskell/ML-like languages, I decided to opt for Elixir and Phoenix for my latest project, simply because of the maturity of the web framework and LiveView. If I weren't building a web app, I'd probably have gone with Gleam instead.
Edit: I do miss static typing, but it's worth it to not have to reinvent the web framework wheels myself.
I love Gleam, but I would start with Elixir if you're interested in learning about how powerful the BEAM & OTP are.
There's not much documentation/resources around OTP in Gleam. When I was playing around with it I often found myself referring to the Elixir docs and then 'translating' that knowledge to Gleam's OTP implementation.
Gleam is still very new so this is totally understandable, and both are great languages so you'll likely have a lot of fun learning either of them.
Erlang is a much better language to learn if you're interested in learning about the BEAM and OTP, and the book "Programming Erlang"[0] is an excellent resource for learning it.
I've used Elixir since 2015 and in fact learned it first. I still think "Programming Erlang" is a much better book than any other for actually learning Erlang and BEAM/OTP principles. Erlang as a language is simpler, leaving more time and energy for learning the actual important bits about OTP.
For me, gleam is a better fit for the reasons I mentioned, but elixir / phoenix is definitely more mature, so I guess it depends what you like and what you want out of it.
Gleam is cool but honestly for now the ecosystem is so much bigger in Elixir. And yes, you can use some libraries across and things like that, but then again you could also bring in the parts that you need from Gleam into Elixir and instead of vice versa. If you just want to learn a really cool language, I think Gleam is pretty cool. But if you want to learn a language that is more productive but still kind of cool, I would start really like here and then dip my toes into Gleam.
I don't tend to benefit from my predictions as things always take longer to unfold than I think they will, but I'm beyond bearish at present. I'd rather play blackjack.
reply