The Crystal Programming Language Forum

Space between `&` and a Proc

I noticed that spaces between & and Proc variable are complained by the compiler:

foo = -> { 1 }

def bar(&)
  yield
end

bar(& foo)
syntax error in eval:7
Error: unterminated call

Then, I found this issue. Is this the same or related?

I created a macro using % variable and found this problem:

macro foo
  %proc = -> { "some code" }
  some_call(& %proc)
end

I find that the space between & and % is not required, and the compiler parses it well. Therefore my problem here is already solved, but I just want to know the reason.

I’m pretty sure having a space after the & is not valid syntax, hence the error. Same problem happens with your macro example (assuming you actually use the macro), see https://play.crystal-lang.org/#/r/9fxm.

See first example in https://crystal-lang.org/reference/syntax_and_semantics/block_forwarding.html

We use & to specify that we really want to pass proc as the block argument.

Yes, I explicitly made & block an error because it looks weird.

4 Likes

hello,

def bar(&)
yield
end

i don’t crystal a lot an just discover this syntax. i try to play with
it and noticed that

foo = -> {1}
bar = -> (&) {yield}

doesn’t work. did i miss something ? do that because one of the most
frustration to me with crystal (i had the same with ruby) is this
“shell alike block” finished by “end”. it would be nice to to brace
our functions (even by abusing the Proc syntax?) … something like


def bar(&) {
    puts "i wanna yield"
    yield
}

# or

def bar -> (&) {
    puts "i wanna yield"
    yield
}

# looks cleaner to me than

def bof(&)
    puts "i wanna yield"
    yield
end

regards
marc

This statement

foo = -> { 1 }

creates a callable object, aka proc, and set it to the variable foo. On the other hand,

def bar
  1
end

defines the method bar onto the current scope (here global). These are different.

A proc can accept another “proc” as an argument, but not for “block”. Only methods can have a block argument.

So you can only do:

foo = -> { 1 }
bar = -> (proc : Proc(Int32)) { proc.call }

bar.call(foo)

… Please correct me if I am wrong.

1 Like

hello,