In Supervisor.start_link, we have three ways to start children
a module
a {module, arg} tuple
a child specification as a map with at least the :id and :start fields
or a tuple with 6 elements generated by Supervisor.Spec (deprecated)
For naming the child, the {module, arg} tuple works fine if the module start_link is start_link(opts \\ []), but for start_link(args, opts), how do we pass in both args and opts? Why don’t we have {module, args, opts} so we can pass in [name: RegisterThisName] so we can refer it with the name later?
How do I give it a name in this case?
children = [
{Module1, name: Module1}
{Module2, name: Module2}
{Module3, %Struct{...}, name: Module3} <—— how to name it?
]
Contrary to the old ˋSupervisor.Specˋ way the new tuple form is not meant to define multiple parameters for start_link. ˋ{mod, arg}ˋ will result in a call to ˋmod.child_spec/1ˋ. That function can only ever be arity-1, so different tuples don‘t make sense.
Within ˋchild_spec/1ˋ you could divide the arguments up again to make the supervisor child by calling ˋmod.start_link/2ˋ, but that will require a custom ˋchild_spec/1ˋ. The default generated by ˋuse GenServerˋ does make the arguments sent to ˋchild_spec/1ˋ be passed to ˋmod.start_link/1ˋ.
I‘ve recently written a blogpost on the topic, if you need more details:
I like the example of {Registry, keys: :unique, name: Registry.ViaTest}. Is it not common to pass a struct into start_link to initialize a GenServer, but instead passing in keyword?