Hacker Newsnew | past | comments | ask | show | jobs | submit | vereis's commentslogin


yeah this is the distinctive ps1 look I think all games look like this, at least polygonal games


You can use lots of tricks to make your PS1 game not look like this. Or at least much less like this.


i think the original quote is "Any sufficiently complicated concurrent program in another language contains an ad hoc informally-specified bug-ridden slow implementation of half of Erlang" :-) but your point still stands



elixir is only better imo because of better tooling, more libraries/bigger ecosystem, and macros

give me macros and I'd be happy (not preprocessor stuff, not parse transforms)


honest q: how do you distinguish between single node erlang applications vs clustered erlang applications?


This returns true if you're on a single node erlang application :P

    erlang:node() == nonode@nohost andalso erlang:nodes(known) == [nonode@nohost]

A single node erlang application would be one that doesn't use dist at all. Although, if it includes anything gen_event or similar, and it happens to be dist connected, unless it specifically checks, it will happily reply to remote Erlang processes.


my personal reality is that the majority of projects I've consulted on have seldom actually leveraged distributed erlang for anything. the concurrency part yes, clustering for the sake of availability or spreading load yes, but actually doing anything more complex than that has been the exception! ymmv tho!


I recommend taking a look at the various open source Riak applications too! Might not be updated to any sort of recent versions of erlang but was a great resource to me early on.


ahoy!! thanks for spotting the issue I wrote the post in a stream of consciousness after a long day! I'll make that edit and call it out!

the statement about what historically constitutes a large erlang cluster was an anecdote told to by Francesco Cesarini during lunch a few years ago — I'm not actually sure of the time frame (or my memory!)

likewise I'll update the post to reflect that! thanks ( ◜ ‿ ◝ ) ♡


ahoy!!! never expected to see any of my posts on hn D:

for the first point it was purposely not written on the beam as otherwise there would be no post!

an original draft of did talk more in depth about replies but it just got convoluted and too long!! maybe I'll try to restore something to this end

granted on the runtime and genserver point (though technically it's just a process that receives messages, nothing so formal as a genserver itself)


Gleam runs on the BEAM


It does. However, its actor implementation is not built upon Erlang/OTP, and currently is “experimental” and not even mentioned on the main site.


> its actor implementation is not built upon Erlang/OTP

This seems to be the opposite of pragmatic.

The most pragmatic approach to actors when you're building a BEAM language would be to write bindings for OTP and be done with it. This sounds kind of like building a JVM language with no intention of providing interop with the JVM ecosystem—yeah, the VM is good, but the ecosystem is what we're actually there for.

If you're building a BEAM language, why would you attempt to reimplement OTP?


Because of type safety. The OTP lib is already great, but there are still some things missing, most requested being named processes. But there is work being done to figure out how to best make it work for gleam.


The question of type safety has come up so often here that I guess it's worth replying:

That's exactly what I mean by this not seeming pragmatic. Pragmatic would be making do with partial type safety in order to be fully compatible with OTP. That's the much-maligned TypeScript approach, and it worked for TypeScript because it was pragmatic.

Now, maybe Gleam feels the need to take this approach because Elixir is already planning on filling the pragmatic gradually-typed BEAM language niche. That's fine if so!


Type safety is one of the goals of the language I don't see a reason to throw it out of the window now. I see what you mean, but the type system is one of the things that makes gleam pragmatic. If you really need some missing OTP feature you can super easily step into Erlang using FFI and get it. That's one of the reasons the article doesn't call gleam pure.


Gleam does not sacrifice OTP compatibility for type safety. It picks both.


And what has this approach gotten them? A language as complex as c++ and haskell combined, but that still has runtime type errors. A typescript backlash is coming.


It uses the same primitives as Erlang, the difference is that it exposes type safe APIs instead of untyped ones which you would get from using the Erlang abstractions.

It implements the same protocols and does not have any interop shortcomings.


I believe their implementation was written to support static typing (since Gleam is a statically-typed language).


I agree with the part about reusing OTP but some of the server syntax of Erlang and Elixir is not good IMHO. I never liked using those handle_* functions. Give them proper names and you cover nearly all the normal usage, which is mutating the internal state of a process (an object in other families of languages.) That would be the pragmatic choice, to lure Java, C++ programmers.


Elixir gives you Agent, which is what you want, but for reasons, Agent is a bad choice.

What you're not seeing with the handle_* functions is all the extra stuff in there that deals with, for example, "what if the thing you want to access is unavailable?". That's not really something that for example go is able to handle so easily.


What would be the proper name to handle a call other than handle_call?


This is Elixir syntax, not Gleam:

Instead of

  defmodule Robot do
    def handle_call(:get_state, _from, state) do
       something()
    end
    def get_state() do
      GenServer.call(__MODULE__, :get_state)
    end
  end
  robot = Robot.start_link()
  robot.get_state()
just let me write (note the new flavor of def)

  defstatefulmodule Robot do
    def get_state() do
      something()
    end
  end
  robot = Robot.new() 
  robot.get_state()
Possibly add a defsync / defasync flavor of function definition to declare when the caller has to wait for the result of the function.

The idea is that I don't have to do the job of the compiler. It should add the boilerplate during the compilation to BEAM bytecode.

I know that there are a number of other possible cases that the handle_* functions can accommodate and this code does not, but this object-oriented-style state management is the purpose of almost all the occurrences of GenServers in the code bases I saw. Unfortunately it's littered by handle_* boilerplate that hides the purpose of the code and as all code, adds bugs by itself.

So: add handle_* to BEAM languages for maximum control but also add a dumbed down version that's all we need almost anytime.


Ok, I kind of see what you're saying, but IMHO, you're trying to hide the central, enabling abstraction of BEAM environments, which is sending messages to other processes.

If you really don't like the get_state above, I think it'd make more sense to just ditch it, and use GenServer.call(robot, :get_state) in places where you'd call robot.get_state(). Those three lines of definition don't seem to be doing you much good, and calling GenServer directly isn't too hard; I probably wouldn't write the underlying make_ref / monitor / send / receive / demonitor myself in the general case, but it can be useful sometimes.

In my experience with distributed Erlang, we'd have the server in one file, and the client in another; the exports for the client were the public api, and the handle_calls where the implementation. We'd often have a smidge of logic in the client, to pick the right pg to send messages to or whatever, so it useful to have that instead of just a gen_server:call in the calling code.


In the early days of Elixir what you are proposing here was popular[1], but over time the community largely decided it wasn't beneficial and I rarely see it any more.

[1]: https://github.com/sasa1977/exactor


IIRC the re-implementation was necessary for type-safety.


It is production ready and has been used for numerous non-trivial projects. Experimental in this context means there is expected to be API changes and feature additions in future.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: