3

How to pass plus into calculate method?

def calculate(&block : (Float64, Float64) -> Float64)
  block.call(1.1, 2.2)
end

def plus(a, b)
  a + b
end

calculate{|a, b| plus a, b}

This won't work

calculate ->plus
calculate &plus

P.S.

Another question, how to make it to work for all numbers? Not just Float64. This code won't compile and complain about requiring more specific type than Number

def calculate(&block : (Number, Number) -> Number)
  block.call(1, 2)
end

Ideally it would be nice to make it generalised so that typeof(block.call(1, 2)) => Int32 and typeof(block.call(1.1, 2.2)) => Float64

Alex Craft
  • 13,598
  • 11
  • 69
  • 133

2 Answers2

6

How to pass plus into calculate method?

You're looking for

calculate(&->plus(Float64, Float64))

Where ->plus(Float64, Float64) returns a Proc. Mind that you have to specify the type of the arguments - see the section From methods in the reference manual.

how to make it to work for all numbers?

I'd look into forall - see the section on Free variables in the reference manual.

erasing
  • 526
  • 3
  • 5
2

A generalized solution could work with free variables, but there's a catch because free variables can't be derived from block arguments:

def calculate(&block : (T, T) -> T) forall T # Error: undefined constant T

This is because block arguments can't be overloaded since they can simply be captured blocks without type restrictions.

There are two options to make this work:

  1. You can pass the type for T explicitly as an argument. This is a bit more verbose but works with a captured block argument.
def plus(a, b)
  a + b
end

def calculate(t : T.class, &block : (T, T) -> T) forall T
  block.call(1.1, 2.2)
end

calculate(Float64, &->plus(Float64, Float64))
  1. You can change the captured block argument to a normal argument receiving a Proc:
def plus(a, b)
  a + b
end

def calculate(block : (T, T) -> T) forall T
  block.call(1.1, 2.2)
end

calculate(->plus(Float64, Float64))
Johannes Müller
  • 5,581
  • 1
  • 11
  • 25
  • Thanks. Actually, I want a normal argument, I added `&` to `Proc` because I thought it's the way it's supposed to be :). – Alex Craft Dec 27 '19 at 14:53