Abbreviation syntax - jesuitically sophisticated?

Hi all,

please consider this:

class Acme(T)
  getter slot

  def initialize(arg : (T))
    @slot = arg
  end
end

def acme?(arg : Acme?)
  arg
end 
      
gizmo = Acme(Int32).new(13)

p! acme?(gizmo).try { |obj| obj.slot * 2 }
p! acme?(nil).try { |obj| obj.slot * 2 }
p! acme?(gizmo).try &.slot * 2

It works as expected but acme?(nil).try &.slot * 2 doesn’t compile:

In src/maybe.cr:22:28

 22 | p! acme?(nil).try &.slot * 2
                                 ^
Error: undefined method '*' for Nil

I thought this is an abbreviation for acme?(nil).try { |obj| obj.slot * 2 }.

What do I miss?

I’m pretty sure it’s parsed as acme?(nil).try(&.slot) * 2. If you want to do something with the return value of .slot in the context of the try, you can’t use the shorthand syntax.

1 Like

Like (acme?(gizmo)).try(&.slot) * 2 # => 26 ? Here I do something with it - which works. Strange - as then it shouldn’t work too. Thanks.

No, that’s the same thing you had before, just with somewhat more explicit (). It’ll suffer from the same problem if you pass nil instead of gizmo. The compiler I guess can prove that the return value from #acme? won’t be nil in this case, so it just works.

If you want it to work all the time, you’ll need to do the long form like the first two calls in the OP.

1 Like

Yeah. That is O.K. - and even better as I can’t remember the short form :crazy_face::sunglasses:

Proper short version code (notice the .* part):

p! acme?(nil).try &.slot.* 2
1 Like

prefer acme?(nil).try &.slot.*(2), because * is a method, . and () notation always has the highest priority.(in almost all programing language)