[HN Gopher] Luerl - An Implementation of Lua in Erlang
___________________________________________________________________
Luerl - An Implementation of Lua in Erlang
Author : sbuttgereit
Score : 64 points
Date : 2021-12-27 16:39 UTC (6 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| sbuttgereit wrote:
| There's also a presentation from several years ago about this
| project by Robert Virding that's worth watching if you're into
| the Erlang eco-system even without need of a Lua implementation
| in Erlang:
|
| https://www.youtube.com/watch?v=A6_bt6tK2Is
| weatherlight wrote:
| One of the inventors or Erlang made this! That's really cool, Who
| is the target audience though? I thought the whole point of using
| something like Lua is that its very fast and can be used to
| augment app written in a low level language (Redis and gaming
| engines come to mind.)
| sbuttgereit wrote:
| For an (Elixir) application I'm building, I'm hoping to use it
| as a scripting engine which allows end users of the application
| to script custom behaviors for the application. It's still
| early days for this project and there are many bigger fish to
| fry than the scripting feature, but my initial impressions are
| that this is a good candidate for this task.
| mrdoops wrote:
| Neat thing about Luerl is that you can manage many isolated Luerl
| vms from within an Erlang supervision model which is a very
| desirable trait for things like games with user defined scripts
| that may explode.
| borski wrote:
| We used this at a work hackathon to enable customers to submit
| custom scripts, written in a Lua API we defined, to add custom
| vulnerability checks to our Elixir-based security scanner. It was
| fantastic.
| petejodo wrote:
| I'd love to hear more about this. Do you have any reading
| material or tutorials that helped you get started?
| pmarreck wrote:
| How tricky is it to simulate mutable variable semantics in a
| fundamentally-immutable language?
| dnautics wrote:
| erlang is not fundamentally immutable. It's just "locally
| immutable". You can't mutate a variable. A function call can
| have side effects, just it can't change its arguments -- but if
| it's argument is, abstractly speaking, a reference [0], it can
| effect a change on the _abstract_ contents of the reference.
| Using this mechanism there are TONS of escape hatches using
| function-called "abstract references".
|
| [0] maybe the reference refers to a file, network socket, a url
| over the internet, which work in the obvious way. It could also
| be things that erlang gives you for free: the id to another
| process (thread) to which you send an instruction, "change your
| internal data", a "process dictionary" (think: thread-local-
| storage ish), "ets tables" (think: a redis/memecached you get
| for free"). If you want to go deeper, it could even be "a
| wrapped, refcounted, C pointer to raw memory", there are ways
| to do this safely that the native interface gives the curious
| low-level programmer.
| Jtsummers wrote:
| A couple of ways: Function parameters with a "state" structure,
| processes (and function parameters).
|
| A common pattern is something like this:
| loop(N) -> Next = do_stuff(N,...), loop(Next).
|
| That would be the first pattern. So you could have a state
| variable (or set of variables) which are changed on the next
| iteration. Since Erlang does tail call elimination, this is the
| same as a while/for loop in other languages but does not have
| explicit mutation. You can also return the new state and thread
| it through various function calls.
|
| With processes, you can do something similar:
| counter(N) -> receive Pid -> Pid ! N,
| end, counter(N+1). user(Count_PID) ->
| Counter_PID ! self(), receive N ->
| io:format("~p times~n", [N]) end,
| user(Counter_PID).
|
| (probably typos above, haven't done Erlang in a while)
|
| Between these two, and more advanced use of language modules,
| you can provide mutable state (of a sort).
|
| EDIT: Also worth noting that, before getting to anything beyond
| the basic syntax, both records and maps permit updates rather
| cleanly. For instance, with a map you might have:
| Map = #{a => 10} Updated = Map#{a := 42}
|
| So if you have a register map and do something like (again,
| been a while so forgive syntax errors):
| update_register(Rs, Register, Value) -> Rs#{ Register
| := Value }.
|
| The rest of the map is left unaltered, only the bit that needs
| to be updated gets changed. And Erlang/BEAM is careful about
| not making more copies than needed so in theory (at one point I
| studied these details, I've forgotten the specifics) this
| should result in very little new memory being allocated for the
| updated map.
| qsort wrote:
| Conceptually, not at all: you simply create a copy of whatever
| data structure you are keeping in memory to bind names to
| values. (Notice that you are probably already using something
| like this to correctly resolve scopes -- so it's not like it's
| more work, either).
|
| In practice, I guess it depends on how much you care about
| performance and how 'smart' the functional runtime is. But if
| you're not writing a toy interpreter, you probably also need
| bytecode compilation, etc.
| bogwog wrote:
| This is awesome, I love seeing weird projects like this. Does
| anyone have a practical use for this, or is it just for fun?
___________________________________________________________________
(page generated 2021-12-27 23:01 UTC)