Passing a function as an argument in Scala / Figaro

I am trying to learn Figaro and since it is implemented in Scala I am running into some Scala problems. For example, the code below Importance.probability

takes two arguments, the first is the distribution and the second is the predicate. But when I try to run this code, I get the following error:

Missing argument for moreThan50

which makes sense since it actually takes one argument.

Since Scala is a functional language, I guess there is some clever standard way of sending functions as arguments that I missed? I tried to use _

to make it partially applied, but it doesn't work.

import com.cra.figaro.library.atomic.continuous.Uniform
import com.cra.figaro.algorithm.sampling.Importance

def greaterThan50(d: Double) = d > 50 
val temperatur = Uniform(10,70) 
Importance.probability(temperatur, greaterThan50)

      

+3


source to share


2 answers


Note that in Scala you can pass a value to a function like greaterThan50

where a function is expected.

In this case, in the method probability

that is defined as

def probability[T](target: Element[T], predicate: T => Boolean): Double

      

the second argument is a function, but why doesn't the compiler accept, when passed greaterThan50

, which is actually the function's value?

This is because Importance

there is another overloaded method that is defined below:

def probability[T](target: Element[T], value: T): Double

      

So when we call

Importance.probability(temperatur, greaterThan50)

      

the compiler does raise the seconds overload method. So it tries to use a method greaterThan50

on some value to get some result in the result that can be used as the second type argument T

.

In this case, to disambiguate, you need to partially apply the function :

Importance.probability(temperatur, greaterThan50 _)

      

which fixes the problem as the type greaterThan50 _

is now equal Double => Boolean

, which is an exact match for the first overloaded function.

Experiment to prove



To make sure this approach works in non-overloaded methods, you can simply try to define the following function in your context (for example in object

):

def probability[T](target: Element[T], predicate: T => Boolean): Double = 10

      

and call it

probability(temperatur, greaterThan50)   // Note that this function is defined by you

      

you will see there is no compilation error as the compiler is expecting a function and you are giving it a function value.

Other options

You can of course pass the literal to the function in probability

:

Importance.probability[Double](temperatur, (x: Double) => x > 50)

      

or you can define greaterThan50

like this:

def greaterThan50 = (d: Double) =>  d > 50

      

which will be of type (Double) => Boolean

, which again is an exact match.

Renouncement

The figaro

version 2.4.0.0

with the Scala version is used 2.11.2

.

+5


source


The reason this doesn't work is because you are calling a different method called probability

than the one you think you are calling.

You call the companion object method probability

that has this signature:

def probability[T](target: Element[T], value: T, numSamples: Int = 10000): Double

      



You probably want something like this:

import com.cra.figaro.library.atomic.continuous.Uniform
import com.cra.figaro.algorithm.sampling.Importance

def greaterThan50(d: Double) = d > 50 
val temperatur = Uniform(10,70)
val alg = Importance(myNumSamples = 100, temperatur)
alg.start()
alg.probability(temperatur, greaterThan50 _)

      

Have a look at Hello World which uses Importance

.

0


source







All Articles