Scratch Supports .Add but not .Sub [Bug or Feature?]

Probably one for the core dev team, this one:

I’ve just been trying to implement a template function which will apply “odd” or “even” classes to alternate divs on a page. The way I’d usually do this would be to set somevar = -1, then subtract -1 from it on each loop and use the resulting -1, 0, -1, 0, -1, 0 ... state of the variable to toggle the classes:

{{ $.Scratch.Set "striper" -1 }}
{{ range .Data.Pages }}
<article class="{{if lt ($.Scratch.Get "striper") 0}}odd{{else}}even{{end}}">
{{ .Content}}
{{ $.Scratch.Sub "striper" -1 }}

Unfortunately, $.Scratch.Sub generates an error:

<$.Scratch.Sub>: Sub is not a field of struct type *hugolib.Scratch

So, given that $.Scratch supports .Add, is the omission of support for .Sub an oversight, or has it been done deliberately for a reason?

I can’t answer your question regarding the implementation of .Scratch, but once I tried to implement the same. Your approach can be simplified by looking what the current index modulo 2 returns. If the result equals 0 it’s even, otherwise odd.

We could add a sub, but will not – as the contract of Add is hard to fulfill in a Sub (think slices and append).

The beauty of integer arithmetic, though, is that:


Would be the same as:


Ah. But it wouldn’t work as to toggle between two values, as per my example above. Because -1 - -1 =0 but -1 + -1 = -2

Anyway, thanks to the Linked Topic posted by @digitalcraftsman above, I managed to knock it into shape, using the code you supplied there. A bit tricky, as my actual range query was a bit more complex than I posted above. But my “if in doubt, hit it with more brackets” approach to coding did the job:

{{ range $index, $loop := (where .Data.Pages ".Params.section" "services") }}
<article class="full {{if modBool $index 2 }}odd{{else}}even{{end}}">
{{ .Content}}

Working like a charm:

Thanks guys!

1 Like