Idiomatic Erlang?

Antonio SJ Musumeci trapexit@REDACTED
Mon Jul 26 13:23:29 CEST 2021


On 7/26/2021 6:19 AM, Benjamin Scherrey wrote:
> Been a couple of decades since I did any Erlang coding from scratch 
> and it seems to have improved significantly (didn't have proper 
> strings back then for example). I have a little hobby project I'm 
> using to get myself up to snuff so I can do some more serious work for 
> an upcoming project. Would appreciate some feedback regarding a few 
> issues/questions. The code can be found at 
> https://github.com/scherrey/dnderl <https://github.com/scherrey/dnderl> .
>
> If you've ever played Advanced Dungeons & Dragons you'll recognize 
> that this is a simple implementation of the THAC0 (to-hit armour class 
> 0) concept from the original combat tables in the Dungeon Masters 
> Guide. So 'combat:thac0(fighter, 5, 2).' would correctly tell you that 
> your 5th level fighter needs to roll a 14 or higher on a 20-sided die 
> to hit an armour class 2 opponent whereas 'combat:thac0(thief, 5, 
> 2).' would tell you that a similar level thief requires a roll of 17 
> or better. Here are my questions:
>
> 1) My top level module is combat.erl ( 
> https://github.com/scherrey/dnderl/blob/master/combat.erl 
> <https://github.com/scherrey/dnderl/blob/master/combat.erl> ). All it 
> really does is introduce the class atom type and re-export 
> combattables:basetohit/3 (albeit under a different name, thac0/3). Is 
> it necessary to create a forwarding function like thac0/3 like I'm 
> doing when I'd really just prefer to establish thac0/3 in the 
> combattables module and re-export it from combat.erl? (Don't read 
> anything into the different names - I just decided to rename it in the 
> top level module because I liked it better and would be happy to use 
> that same name throughout.) Attempting to re-export a function 
> declared in another module gives me an error.
>
>
> 2) In combattables.erl ( 
> https://github.com/scherrey/dnderl/blob/master/combattables.erl 
> <https://github.com/scherrey/dnderl/blob/master/combattables.erl> ) I 
> put monster_offset/1 as its own function because I couldn't figure out 
> syntax for how to get the result of the if statement as an 
> intermediate variable which I would have put inside the last 
> basetohit/3 implementation. I tried several things but nothing that 
> seemed correct to me would compile so I had to break it out into its 
> own function. I feel like I'm missing something obvious but perhaps 
> it's simply not allowed?
>
>
> 3) Is the way I've overloaded basetohit/3 with guards depending on 
> which class is passed in the preferred idiomatic way to implement such 
> a construct in Erlang? I thought of trying 'case' or 'if' but this 
> seemed "cleanest" to me. I generally avoid if statements whenever 
> possible in my other programming languages like C++ & Python. 
> Appreciate any insights for such circumstances.
>
>
> 4) Is there no such thing as a module scope for a variable in Erlang? 
> In combattables.erl I have 4 functions that return tuples representing 
> the combat tables for each class. My initial thought was that they 
> would be variables that could be referenced by any function in the 
> module but that doesn't seem to work. The tuples in this case are 
> constant lookup tables not to be updated. Am I doing this in the 
> "correct" idiomatic manner for Erlang?
>
>
> thanks & best regards,
>
>  -- Ben Scherrey

1) Not sure what you mean by "necessary". You can't create proxies 
automagically. If you want combattables to be, in effect, a private 
module and combat the be the public API then yes. As with most languages 
you would manually wrap it like that.

2) Just assign the if statement to a variable: 
https://erlangbyexample.org/if-else

I would still keep it as a function for cleanliness and readability but 
everything has a return value.

3) That's fine though I would perhaps have done it in a more verbose way 
for readability but the result would be basically the same.

basetohit('cleric',Level,AC) ->
...;
basetohit('druid',Level,AC) ->
...;

Or keep some grouping identifier around if those groupings are possibly 
used more than once to simplify matching on those groups.

4) As in a global? No. What you've done is fine. Those hard coded data 
structures are optimized by the compiler just as you'd find in most 
compilers where you have const readonly data. There are other ways you 
could implement that but that'd likely be the most efficient.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20210726/0fee23be/attachment.htm>


More information about the erlang-questions mailing list