HUGO

How to check for nil resource

I have a resource $res that is loaded via $page.Resources.GetMatch. It might be nil, because the resource might not exist.

Now I want the following expression:

(cond $res (printf "%s %sw," $res.RelPermalink $res.Width) "")

Does not work, cond expects a bool (although (cond (not $res) seems to be valid, cond expects a bool but not does not?).

So let’s booleanize the parameter:

(cond (not (not $res)) (printf "%s %sw," $res.RelPermalink $res.Width) "")

This throws:

execute of template failed: template: partials/mysite/mylayout.html:43:84: executing "partials/mysite/mylayout.html" at <$res.RelPermalink>: nil pointer evaluating resource.Resource.RelPermalink

Uh, I’m explicitly checking if the resource is nil or not, but I get a nil pointer exception anyway?

{{ with $page.Resources.GetMatch }}
  {{ printf "%s %dw," .RelPermalink .Width }}
{{ else }}
  ...
{{ end }}

Isn’t it possible in one expression? If not, why not?

In other words, why doesn’t my code work? Why do I get a nil pointer exception after explicitly testing for nil?

(and less important: why does not accept non-bools but cond does not?)

Eager/greedy evaluation.
See https://en.wikipedia.org/wiki/Evaluation_strategy#Strict_evaluation.

And can I disable or circumvent greedy evaluation in this case?

Yes, circumvent using the with construct in my original reply.

See also: https://github.com/gohugoio/hugo/issues/5792

I see, thanks.

(sometimes when programming Hugo templates, I get the feeling that programming languages in the 1990s were more versatile and programmer-friendly than Hugo templates…)

The thing is, I need to assign the result of the cond expression to a variable that is later used across several HTML tags. So what I need is something like that:

{{ $var := "" }}
{{ with $page.Resources.GetMatch }}
  {{ $var := printf "%s %dw," .RelPermalink .Width }}
{{ else }}
  {{ $var := "" }}
{{ end }}
...
<div data-xy="{{ $var }}">
...
<p data-xy="{{ $var }}">

The problem now is another quirk of Hugo templates: variables that are assigned inside a block (like with) do not keep their assigned value outside of the block. So the above code would not work. I could use a Scratch, but is that really necessary?

Yes I could extract this into a separate template, but that gets very complicated because of other reasons.

Is there any way I can assign to a variable something that depends on a resource?

Initialize ( := ) outside the block, and assign ( = ) within.

{{ $var := 0 }}
{{ if true }}
  {{ $var = 1 }}
{{ else }}
  {{ $var = 2 }}
{{ end }}

Wow okay. So my assumption was wrong, that variables won’t keep their assigned values outside a block. I’m pretty sure I have read that somewhere on this forum, but anyway.

Thanks for your help!

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.