Optimization for nillable var check and code

Is there something terser than this:

getter tex : LibSDL::Texture*?

def render
  tex = @tex
  return unless tex
  LibSDL.set_texture_alpha_mod(tex, 255)
  ...
end

Original code, rejected by the compiler, being :

getter tex : LibSDL::Texture*?

def render
  LibSDL.set_texture_alpha_mod(@tex.as(LibSDL::texture*), 255) if @tex
  ...
end

# compilation error
# Error: can't cast (Pointer(LibSDL::Texture) | Nil) to Pointer(LibSDL::Texture)

Could at least save a line via return unless tex = @tex. Is there a world in which @tex just isn’t nilable so you could avoid doing a nil check at all?

Why is @tex even nilable? The type declaration is tex : LibSDL::Texture*… No Nil there.

1 Like

Even if @tex weren’t nilable, you’d probably still need the same check against null pointers (they are also falsey).

Since @tex is inferred to be the nilable Pointer | Nil type in your program, you must assign it to a local variable to reduce its type to Pointer:

if tex = @tex
  LibSDL.set_texture_alpha_mod(tex, 255)
end

You might also want to understand why @tex is inferred (or declared) as a nilable, and try to avoid it. That would use less memory, and you could use @tex directly (or still do an if check to rule out NULL pointers).

Thanks for your comments. I had to declare Widget.tex as LibSDL::Texture*? because it is only created in sub classes.

abstract class Widget
  getter ctx : AppContext
  getter bounds : LibSDL::Rect
  getter tex : LibSDL::Texture*?

  def initialize(@ctx, @bounds)
    ...
    generate
  end

  abstract def generate

  def render
    return unless tex = @tex
    LibSDL.set_texture_alpha_mod(tex, 255)
    ...
  end
end

class ColorButton < Widget
  property color : UInt32 = 0x000000FF

  def initialize(@ctx, @bounds, @color)
    super(@ctx, @bounds)
  end

  def generate()
    ...
    @tex = LibSDL.create_texture_from_surface(@ctx.renderer, surface)
    ...
  end
end

Why is @tex even nilable? The type declaration is tex : LibSDL::Texture*… No Nil there.

My mistake. Will fix extracted code. Thanks.

getter! tex : LibSDL::Texture*

This at least would allow you to skip checking for nil, yet as @HertzDevil pointed out you might want to check for text.null? anyway :man_shrugging: