HNHacker News
TopNewBestAskShowJobs

innocentoldguy

1,110 karma · joined May 5, 2015

[ my public key: https://keybase.io/innocentoldguy; my proof: https://keybase.io/innocentoldguy/sigs/CgYSzHuI8_U9QF-lmwZpb1FTyydeDAomZIlqui26W0U ]
submissionscomments
innocentoldguy··on Japan to revise romanization rules for first time in 70 years
We are talking about writing/spelling, aren't we?

Why would you want to confuse the hell out of those learning Japanese by spelling せんせい (sensei) using an E with a macron, a la "sensē," when that is not at all how you spell it or type in phonetically in an IME? Having a one-to-one romanization for each Hiragana phonetic is far more logical for learners, who are essentially the target of romanized Japanese, than creating a Hooked on Phonics version that is completely disconnected from writing reality.

I also think your comment, written in Japanese, saying, "This stupid nonsense isn't going to be of any use to anyone," is both ignorant and uncalled for.

innocentoldguy··on Japan to revise romanization rules for first time in 70 years
> In Japanese, an E column kana followed by I sometimes makes a long E, like in 先生 (sen + sei -> sensē).

While it is sometimes difficult to discern the combined E and I sound, especially for non-native speakers, the word 先生 (sensei) is technically pronounced "sensei" and should be spelled that way to distinguish it from words with long E sounds, such as ええ (ee) and お姉さん (oneesan). Similarly, the OU in 東京 (toukyou) and the OO in 大きな (ookina) are different and should be spelled differently. I hope this helps.

EDIT: Added a comma.

innocentoldguy··on I tried Gleam for Advent of Code
- No state machine behaviours. Gleam cannot do gen_statem.

- Limited OTP system messages. Gleam doesn't yet support all OTP system messages, so some OTP debugging messages are discarded by Gleam.

- Gleam doesn't have an equivalent of gen_event to handle event handlers.

- Gleam doesn't support DynamicSupervisor or the :simple_one_for_one for dynamically starting children at runtime.

innocentoldguy··on I tried Gleam for Advent of Code
I don’t mean to minimize the huge effort by the Gleam team; however, Elixir cannot become Gleam without breaking OTP/BEAM in the same ways Gleam does. As it stands now, Elixir is the superior language between the two, if using the full Erlang VM is your goal.
innocentoldguy··on Rubio stages font coup: Times New Roman ousts Calibri
And, he delivers the line with such perfection.
innocentoldguy··on Thoughts on Go vs. Rust vs. Zig
I find Elixir and Erlang easier, but I'm still a neophyte with Rust, so I may feel differently in a year.
innocentoldguy··on How good engineers write bad code at big companies
> I'd love to hear more about this!

He deployed our applications using Kubernetes and refused to implement libcluster. There was something else, too, but I can't recall what it was. It was seven years ago.

> Yeah, this is weird...

I kept telling this developer that you're supposed to test your private functions through your public interfaces, not expose your private functions and hope nobody uses them (which they did), but that fell on deaf ears. He was also a fan of defdeligate and used it EVERYWHERE. Working with that codebase was so annoying.

innocentoldguy··on How good engineers write bad code at big companies
I worked for a company writing Elixir code several years ago. Prior to my arrival, the ignorant architect had deployed Elixir in a way that broke the BEAM (which he viewed as "old and deprecated"). Furthermore, one of the "staff" engineers—instead of using private functions as they're intended—created a pattern of SomePublicModule and SomePublicModule.Private, where he placed all the "private" functions in the SomePublicModule.Private module as public functions so that he could "test them."

I tried almost in vain to fix these two ridiculous decisions, but the company refused to let code fixes through the review process if they touched "well-established, stable code that has been thoroughly tested." After being there for a couple of years, the only thing I was able to fight through and fix was the BEAM issue, which ultimately cost me my job.

My point in all this is that, at least sometimes, it isn't good engineers writing silly code, but rather a combination of incompetent/ignorant engineers making stupid decisions, and company policies that prevent these terrible decisions from ever being fixed, so good engineers have no choice but to write bad code to compensate for the other bad code that was already cemented in place.

innocentoldguy··on Gleam OTP – Fault Tolerant Multicore Programs with Actors
Wouldn't you just `cast` instead of `call` if you thought this was going to be an issue?
innocentoldguy··on Gleam OTP – Fault Tolerant Multicore Programs with Actors
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.

innocentoldguy··on Gleam OTP – Fault Tolerant Multicore Programs with Actors
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.
innocentoldguy··on Gleam OTP – Fault Tolerant Multicore Programs with Actors
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.

innocentoldguy··on Elixir 1.19
I'm sorry you had a bad experience, but this doesn't reflect the experience of most Elixir programmers. I'll share my experience as a counterpoint.

> On a production build, stack traces look like Erlang code...

Elixir has the most readable stacktraces of any language I've used. Here's an example (which is color-coded in the terminal for even more clarity and, as you can see, doesn't contain any Erlang code):

  == Compilation error in file lib/app_web/live/authentication/settings.ex ==
  ** (MismatchedDelimiterError) mismatched delimiter found on lib/app_web/live/authentication/settings.ex:96:1:
    error: unexpected reserved word: end
     │
   4 │   on_mount {AppWeb.UserAuth, :require_sudo_mode
     │            └ unclosed delimiter
  ...
   96 │ end
    │ └ mismatched closing delimiter (expected "}")
    │
    └─ lib/app_web/live/authentication/settings.ex:96:1
It's easy to see that the issue is on line 4, and that it is a missing curly brace.

> Then you have macros, which make code unmaintainable...

Elixir gives you full access to the AST, making macros extremely easy to read and reason through. The point of the Lisp-style macros Elixir uses is to simplify your code. If your code becomes unmaintainable due to your use of macros, you're probably misusing them. I'd have to see a sample to make that determination, though.

> Running "mix xref graph" on most Elixir projects shows a spaghetti mess.

Spaghetti? It's a simple two-level tree that is in alphabetical order. Here's an example, and it is like this all the way down:

  Compiling 26 files (.ex)
  Generated stow app
  lib/app.ex
  lib/app/accounts.ex
  ├── lib/app/accounts/user.ex (export)
  ├── lib/app/accounts/user_notifier.ex
  ├── lib/app/accounts/user_token.ex (export)
  └── lib/app/repo.ex
  ...
To me, this output seems extremely accessible.

> The toolchain has much room for improvement...

Having developed many Windows apps using Borland's tools in the 80s and 90s, I disagree with this statement for these reasons:

• Mix is one of the best and most integrated build tools/task runners I've used. For example, you can create, migrate, and reset databases, execute tests, lint code, generate projects, compile, build assets, install packages, pull dependencies, etc.

• ExUnit is a great testing framework that handles all kinds of tests in an easy-to-read DSL similar to Ruby's RSpec.

• IEx is a fantastic REPL.

• Elixir's debugging tools are excellent. For example, IEx.pry lets you stop all processes and interact with your system in that frozen state in the REPL. You can watch variables, run functions, and even create new functions on the fly to interact with your data to see how it behaves in different scenarios.

> Building a team around Elixir is hard.

Why is it hard? I've worked exclusively on Elixir projects for both start-ups and large companies with hundreds of engineers for over ten years now, and never had a problem with hiring teams.

> And the documentation for most of the projects you will use is full of noise, with few workable examples, grandiose claims of performance, and fantastic treasures, and the articles are a great read if you want to waste your entire evening.

All technical documentation could be improved, but Elixir's is already quite good. See for yourself: https://hexdocs.pm/elixir/1.19.0/Kernel.html.

Furthermore, from within IEx, you can type:

  function |> h
for any function and see an explanation of what the function does and examples of how to use it.

> Support for massive concurrency is nice, but you are realistically not going to need it...

Elixir supports minute concurrency as well, and yes, I do need it. For example, in Ruby on Rails, which has a GIL, I'd have to use a gem like Sidekiq to push long-running processes into Redis so they can be processed in the background. In Elixir, I can just run them in a separate, concurrent process, which is simple.

Here's an example that takes a collection of users and a function and then runs each user through that function, each in a separate thread:

  defmodule ParallelProcessing do
    def map(collection_of_users, func) do
      collection_of_users
      |> Enum.map(&(Task.async(fn -> func.(&1) end)))
      |> Enum.map(&Task.await/1)
    end
  end
Here's the same Elixir code running in a single thread.

  defmodule SequentialProcessing do
    def map(collection_of_users, func) do
      collection_of_users
      |> Enum.map(func)
    end
  end
In the first example, I could have 1 user, 1,000 users, or 1,000,000 users, and this code would run as optimally as possible on all the cores in my CPU or across all the cores in all the CPUs in my multi-server BEAM cluster. There are no extra programs or libraries needed. In the second example, users are processed one at a time, similar to languages like Python, Ruby, JavaScript, PHP, and Perl.

Given the simplicity of writing parallel code in Elixir, why would I limit myself to one CPU core to perform a task when I can use all cores simultaneously?

> Or deal with people that won't stop selling you how great the language is.

The reason they won't stop selling you on Elixir is that Elixir is a fantastic language. I hope you take the time to revisit it in the future. It really is much better than most things out there.

innocentoldguy··on Elixir 1.19
Hi, 15155. May I clarify a couple of things?

1. Regarding Python's GIL: The issue isn't memory sharing between threads. Java and Go allow you to do this, too, but they don't have GILs. The reason Python has a GIL is that it uses reference counting for memory management. If it didn't have a GIL, multiple threads could simultaneously manipulate reference counts, which would lead to memory corruption/leaks.

2. You can share massive "objects" between BEAM processes. For example, if you're running BEAM in a 64-bit environment, you can share maps, structs, and other data structures that are up to 2,305,843,009,213,693,951 bytes in size.

I hope this information helps. I also hope it is correct. I think it is, but I've been wrong before.

innocentoldguy··on Elixir 1.19
Python has a GIL and is mutable, which makes concurrency impossible and error-prone, respectively. Elixir doesn't have a GIL and is immutable.
innocentoldguy··on Elixir 1.19
Gleam doesn't give you access to the full amazingness of OTP and BEAM. Elixir does.
innocentoldguy··on Show HN: WeUseElixir - Elixir project directory
There are open source projects on the site, such as Oban and Absinthe. Is that what you’re looking for or did you mean something else?
innocentoldguy··on Delphi 13 Florence Released
My first programming job was writing Delphi code. Their documentation was excellent. All of the documentation I've used since then has been sad and disappointing.
innocentoldguy··on No adblocker detected
There needs to be a balance. I don't block ads on sites that respect me enough not to drown out the main content with ads. However, I always block sites that have excessive ads or use pop-ups. On a side note, whoever invented pop-up ads should be sentenced to life in prison on a diet of pickled beets and prune juice.
innocentoldguy··on Show HN: I'm making an open-source platform for learning Japanese
It looks great. I would suggest changing the kanji next to the label "Kanji" to 字 instead of 出, though. 字 is the second character in the word 漢字 (kanji) and means "character." I would also suggest changing the kanji next to the "Vocabulary" label from 言 to 語. 語 is the second character in the word 単語 (tango) and means "word." The あ next to the "Kana" label is perfect.

出 means "to go out or exit" and doesn't have anything to do with learning Kanji. 言 means "to say" and is only tangentially related to learning vocabulary.

Still, great job!

innocentoldguy··on Grok Code Fast 1
You don’t have to keep your hands on the wheel.
innocentoldguy··on Grok Code Fast 1
What do you mean by “it still doesn’t work“? I never drive anymore because my Tesla does such a fine job of doing it for me.
innocentoldguy··on Gleam v1.12
Gleam's type system is the root cause of the problem. Please see my reply to the parent of your post.
innocentoldguy··on Gleam v1.12
It has been a while since I looked at Gleam. Some things may have changed. However, the last time I used Gleam, I was forced to switch back to Elixir because Gleam:

• Lacks support for named processes.

• Has limited actor abstractions.

• Doesn't support OTP system messages.

• Has implemented supervisors in a way that can lead to improper shutdowns, data loss, and deviations from the expected BEAM behavior.

• Doesn't support pattern matching directly in function definitions. Instead, it requires you to use case statements.

• Doesn't support global mutable variables because it has no way to track variable types and state changes when BEAM modifies these variables, which is one of the hallmark features of BEAM.

• Doesn't support hot code reloading.

All of these features, which are readily available in Erlang and Elixir, are far more important to me than static typing. I've used statically typed languages like C, C++, C#, and Java, and dynamically typed languages like Python, Ruby, and Elixir throughout my 30+ years career. I've never once lamented not having static types, nor have I ever jumped for joy when I do. For me, static vs. dynamic typing is largely irrelevant and doesn't affect my work one way or the other.

innocentoldguy··on Bluesky: Updated Terms and Policies
You mean like this?

https://d2u3dcdbebyaiu.cloudfront.net/uploads/atch_img/391/b...

innocentoldguy··on Gleam v1.12
I prefer Elixir's syntax over Gleam's, but my main issue with Gleam is architectural. Specifically, Gleam had to bastardize BEAM and OTP to implement static typing. To me, static typing vs. dynamic typing is like having a shelf with a doily vs. one without a doily (the shelf works fine either way), so messing up a solid Actor Model implementation, for instance, for the sake of static typing seems like the wrong thing to do.
innocentoldguy··on Steam, Itch.io are pulling ‘porn’ games. Critics say it's a slippery slope
Here you go:

https://www.nytimes.com/2019/10/12/us/pornhub-sex-traffickin...

https://www.state.gov/reports/2024-trafficking-in-persons-re...

https://www.tokyoreporter.com/japan-news/breaking/npos-more-...

https://www.justice.gov/usao-sdca/pr/girlsdoporn-owner-micha...

https://www.latimes.com/world/asia/la-fg-japan-porn-20160613...

innocentoldguy··on Steam, Itch.io are pulling ‘porn’ games. Critics say it's a slippery slope
In some ways, porn is more damaging, isn't it? For example, there's a lot of sex trafficking going on in the porn industry, but not so much in the censorship industry.

I strongly oppose censorship and believe that payment processors and banks should be prohibited from engaging in it. Still, I have to admit that porn can be extremely destructive.

innocentoldguy··on Swift-erlang-actor-system
Elixir and Erlang outperform Go when under sustained load, so it may not be necessary to write a GenServer in Swift to achieve Go's performance.

The top four areas where I've seen Elixir and Erlang outshine Go are concurrent workloads, memory management, fault-tolerance, and distributed systems.

innocentoldguy··on Org tutorials
I switched from Obsidian to Logseq because Logseq has better block-level support, better embedded image previews, and more functionality out of the box without having to rely on plugins

Why not Notion or Joplin? I like Logseq's outline format better than Joplin's long-form note taking format, and I just don't like Notion at all for purely subjective reasons.

← PreviousPage 2 of 34Next →