Issues using APPLY with my partial

I have a shortcode that accepts a variable number of distinct parameters that are formatted and sorted. When sorted, certain items are placed at the front in a particular order, and all others are added to the end in the order they were received.

I have this working with the following code. Duplicate parameters are removed by uniq, and the remaining parameters are pushed through a partial that may reformat the text. The partial returns a string, and the result is appended to $keys. Finally, the intersect takes $modifiers (in the order they should appear in the final results) and $keys so that a collection of matching modifiers is created in the desired order. That collection is then passed to union along with $keys.

This code works:

{{- $modifiers := slice "Ctrl" "LCtrl" "RCtrl" "Alt" "LAlt" "RAlt" "Opt" "LOpt"
    "ROpt" "Shift" "LShift" "RShift" "Win" "LWin" "RWin" "Cmd" "LCmd" "RCmd" "Fn" }}

{{- $keys := (slice) }}
{{- range .Params | uniq }}
{{-     $keys = $keys | append (partial "func/getKey.html" (. | safeHTML)) }}
{{- end }}

{{- $sorted := union (intersect $modifiers $keys) $keys -}}

Having read the docs on apply, I thought this code might simply things and replace the range loop with a a single statement:

{{- $modifiers := slice "Ctrl" "LCtrl" "RCtrl" "Alt" "LAlt" "RAlt" "Opt" "LOpt"
     "ROpt" "Shift" "LShift" "RShift" "Win" "LWin" "RWin" "Cmd" "LCmd" "RCmd" "Fn" }}

{{- $keys := apply (.Params | uniq) "partial" "func/getKey.html"  "." -}}

{{- $sorted := union (intersect $modifiers $keys) $keys -}}

For some reason, I receive an error with the union stating that “value of type interface {} is not assignable to type string”. I have no idea what that means, and the web searches I completed turned up nothing useful.

at <union (intersect $modifiers $keys) $keys>: error calling union: reflect.Set: value of type interface {} is not assignable to type string

I tried simplifying things more just to get it to compile:

{{- $sorted := apply .Params "partial" "func/getKey.html"  "." -}}

But now I receive a different error.

at <apply .Params “partial” “func/getKey.html” “.”>: error calling apply: partial that returns a value needs a non-zero argument.

Is something wrong with my partial?

Here’s a truncated version of “func/getKey.html”:

{{ $key := lower . }}
{{ if (eq $key "control") }}{{ $key = "Ctrl" }}
{{ else if (eq $key "option") }}{{ $key = "Opt" }}
{{ else if (eq $key "command") }}{{ $key = "Cmd" }}
{{ else if (eq $key "windows") }}{{ $key = "Win" }}
{{ else if (eq $key "function") }}{{ $key = "Fn" }}
{{ else if eq $key "escape" }}{{ $key = "Esc" }}
---//---
{{ else }}{{ $key = title $key }}{{ end }}
{{ return printf "%s" $key}}

I’m running Hugo server hugo v0.85.0-724D5DB5+extended windows/amd64 BuildDate=2021-07-05T10:46:28Z VendorInfo=gohugoio with the following arguments “-D --disableFastRender --bind={local IP} --baseURL={url} -p {port}” I’m going to see if a new build changes this behavior.

I did discover that when calling the shortcode from markdown content files, I don’t normally need to quote alphanumeric parameters, such as {{< foo p1 p2 p3 >}}. However when passing and unquoted 0, the apply/partial call was generating the “partial that returns a value needs a non-zero argument” error. When I changed the parameter to "0", that error went away. Why does this happen? Shouldn’t the unquoted 0 work? It does when I use the loop instead of apply.

I still have some type of issue with the apply and union where “value of type interface {} is not assignable to type string”.

{{- $keys := apply (.Params | uniq) "partial" "func/getKey.html"  "." -}}
{{- $sorted := union (intersect $modifiers $keys) $keys -}}

$modifiers is a slice containing strings.
What is the type of $keys? I assumed it would be a slice or array (still somewhat confused over the difference) and that it also contains the strings returned by the partial.

markdown

{{< foo "Option" "OPTION" "command" "CONTROL" "zebra" "APPLE" >}}

layouts/partials/func/getKey.html

{{ $lookup := dict
  "control" "Ctrl"
  "option" "Opt"
  "command" "Cmd"
  "windows" "Win"
  "function" "Fn"
  "escape" "Esc"
}}
{{ return or (index $lookup .) (title .) }}

layouts/shortcodes/foo.html

{{ $modifiers := slice
  "Ctrl" "LCtrl" "RCtrl" "Alt" "LAlt" "RAlt" "Opt" "LOpt" "ROpt" "Shift"
  "LShift" "RShift" "Win" "LWin" "RWin" "Cmd" "LCmd" "RCmd" "Fn"
}}
{{ $params := apply .Params "lower" "." | uniq | sort }}
{{ $keys := apply $params "partial" "func/getKey.html" "." }}
{{ $sorted := union (intersect $modifiers $keys) $keys }}
{{ delimit $sorted ", " }}

output

Ctrl, Opt, Cmd, Apple, Zebra

That’s just a limitation of the return function.

layouts/partials/render-value.html

{{ . }}

layouts/partials/return-value.html

{{ return . }}

partial calls

{{ partial "render-value.html" 0 }} --> 0
{{ partial "return-value.html" 0 }} --> ERROR partial that returns a value needs a non-zero argument