Why short-argument syntax doesn't work?

I’m learning Crystal and I’ve trying to use the short-argument syntax (that is explained here) in a custom function that receives a block and an array, and modifes its values. My code is:

numArr = [1, 2, 3, 4, 5]

def modify_elements(arr)
  (0...arr.size).each do |i|
    arr[i] = yield arr[i]
  end
  arr
end

modify_elements(numArr) do |arg| # Works
  arg.*(10)
end

modify_elements(numArr) &.*(10) # Doesn't work

puts numArr

The compiler throws me this error:

Syntax error in main.cr:16: unexpected token: .

modify_elements(numArr) &.*(10)
                         ^

I can’t understand why that line of code doesn’t work. If anyone can help me, it will be great!

Try with:

modify_elements(numArr, &.*(10))

& is always a block argument

1 Like

An example of using the short syntax with a method that has at least one argument is missing from the docs. PRs to improve this are welcome :-)

2 Likes

Thanks, it works now :).

At that point my mind was screaming: « Argh! just do arg * 10 »
(Though I know you did it for experimental purposes)

1 Like

Note that all operator method calls x + y are expanded to x.+(y) internally by the compiler, so x.<any operator>(y) is always valid, not just in “a custom function that receives a block”

1 Like

Thanks for the explanation! And yes, I know that I also could have done arg * 10 instead of arg*.(10), but I was testing the language. I’ve also noticed that I should have named the array using snake_case to follow the style guidelines.

kinxer‘s answer is correct.
Foolish i am. ⊙﹏⊙‖∣°
Put all the args in parentheses,or just forget parentheses.

Actually, you don’t need the parentheses: https://carc.in/#/r/6ly2.

def map_parabola(a, b, c, &block_arg : Array(Int32) -> String)
  arr = Array(String).new
  (1..10).each do |x|
    arr << yield [x, a * x**2 + b * x + c]
  end
  arr
end

arr = map_parabola 1, 2, 3, &.to_s

p arr

Output:

["[1, 6]", "[2, 11]", "[3, 18]", "[4, 27]", "[5, 38]", "[6, 51]", "[7, 66]", "[8, 83]", "[9, 102]", "[10, 123]"]

You just can’t add parentheses and also put the short-argument string outside of them: https://carc.in/#/r/6ly3

def map_parabola(a, b, c, &block_arg : Array(Int32) -> String)
  arr = Array(String).new
  (1..10).each do |x|
    arr << yield [x, a * x**2 + b * x + c]
  end
  arr
end

arr = map_parabola(1, 2, 3) &.to_s

p arr

Output:

Syntax error in eval:9: unexpected token: .
1 Like