0

I'm making a DSL in crystal, and I'm trying to get a syntax like ~{do_something}

I tried something like this:

def ~(&block)
  block.call
end

def my_func
  puts "hello"
end

~ { my_func }

But all I get is this error:

Error in line 11: undefined method '~' for Tuple(Nil)

https://carc.in/#/r/1oyv

I tried to replace {...} with do; ...; end without much success:

~ do; my_func; end

And I got:

Syntax error in eval:11: expecting token 'EOF', not 'end'
  1. Can you explain why to I get theses error ?
  2. Is there a way to make this syntax to work ?
bew
  • 483
  • 4
  • 9

1 Answers1

2

~ is parsed as a bitwise complement unary operator (see the language reference), it is only valid as a method name when being called on an object (foo.~) or used an an operator (~foo, does the same as previous example).

In your code, ~ { my_func } is being parsed as a tuple literal ({my_func}, type Tuple(Nil) as my_func returns nil) with the ~ operator used on it. As Tuple doesn't implement that operator (it's not binary, you can't take a bitwise complement of it), you get that error. For the second error, do; code; end blocks cannot exist on their own so you get said syntax error.

I don't think there's a way to implement the exact syntax you want, choose a valid method name for your ~ function.

Stephie
  • 3,135
  • 17
  • 22
  • Thanks, currently I fall back to something like: `var = ~ MyObj.new { my_func }` – bew Mar 06 '17 at 09:51