Sort inputs to function with named arguments

107 views Asked by At

I have a function that takes a mix of positional and named arguments (with the positional arguments being nameable if so desired per usual).

#let monster(
  name, 
  desc: "", 
  strikes: 1, 
  hits_on: 3,
  points: (),
  attacks: 1,
  doc: []
) = {

However I want to sort the values input to the same function that is called multiple times. To this I believe I need to store the inputs into an array, and use sorted on it, before then passing the sorted inputs as arguments to the function itself. This looks something like

#let monsters = ( 
  (
    name: "Goblin",
    desc: "Small evil subserviant humanoid", 
    doc:lorem(20),
  ),  
  (
    name: "Orc", 
    doc: lorem(10),
    hits_on: 3,
  ),
  (
    name: "Wight",
    desc: "Sentient flesh-eating undead",
    strikes: 3,
    points: (
      [When taking a strike from a #monster, MR or be paralyzed for the scene.],
      [Loses a strike each turn spent exposed to sunlight.]
    )
  ),
  (
    name: "Zombie",
    strikes: 2, 
  ),
  (
    name: "Skeleton",
  )
).sorted(key: m => m.name).map(m => monster(..m)).join()

However in the above I have had put the name key for each entry, and make name optional to the monster function or it won't "spread" (the ..m part above). I don't want to do that, I'm anticipating doing something like this array a whole lot more, and expect to have many positional arguments and I don't want to have to name them.

How can I store and apply positional and named arguments in the way I want?

1

There are 1 answers

0
sitandr On

It is impossible to expand dictionaty into both named and positional arguments. However, it is very easy to fix your solution to pass that positional argument:

.sorted(key: m => m.name)
.map(m => monster(m.remove("name"), ..m))
.join()

The trick there is that remove not only removes the key, but also returns the stored value.