pakoito
03/25/2020, 3:34 AMSo I want to minimize both the necessary calculations as well as the traversals, creating no intermediate data structures.Sequence it is then, or plain old imperative code
Jakub Pi
03/26/2020, 3:52 AMclass matcher(private val similarity: Similarity, private vararg val f : BiPred) {
fun bind() : (Data) -> (Data) -> EnumSet<Similarity> =
{ data ->
{ otherdata -> f
.map{ partial(data, it) }
.fold(true) { acc, func -> acc && func(otherdata)} //TODO can short-circuit here
.let { if (it) EnumSet.of(similarity) else EnumSet.noneOf(Similarity::class.java)}}
}
companion object {
fun bind (matchers : List<matcher>) : (Data) -> (Data) -> EnumSet<Similarity> {
return when (matchers.size) {
0 -> { _ -> { EnumSet.noneOf(Similarity::class.java) } }
1 -> matchers.first().bind()
else ->
{ d: Data ->
{ d2: Data ->
matchers
.map { matcher -> matcher.bind() }
.fold(EnumSet.noneOf(Similarity::class.java)) { acc, f ->
acc.apply { addAll(f(d)(d2)) }
}
}
}
}
}
}
}
Ended up with this, which gives me the most flexibility. I can decide later how to invoke it. Is there a better name than bind? That probably has a very specific meaning in FPpakoito
03/26/2020, 12:18 PMfun bind() :
this is a specific version of a general pattern, which is curryingfun bind(d: Data, d1: Data) = TODO()
(::bind).curried()
you'll do the sameval
insteadJakub Pi
03/26/2020, 2:47 PM.uncurried()
which will convert my bind into a regular function. Don't quite understand what you mean by your last point. My curried function is a return value, so nothing should be allocated unless I invoke bind()
which is just a regular function. I can see how having a curried function results in an extra allocation due to an intermediate object being returned on invocation with the first parameter. But what do you mean by making it a val? you mean instead of using fun?
Looking at it another way, my matcher
class is really a factory for comparison operations, so I could rename bind()
to comparator()
. Would it be more efficient to return (Data, Data) -> EnumSet<Similarity>
to avoid currying altogether?pakoito
03/26/2020, 2:52 PMJakub Pi
03/26/2020, 2:53 PM{ d, d2 ->
then assign the return value to a val
pakoito
03/26/2020, 2:53 PMlet myFun x y = x + y
let plusOne x = myFun 3
.code
part of the binary, so to speakval myFun = { x -> { y -> x + y } }
.code
part of itclass Bla {
def x = 1
def bla y = y + x
}
and when you create a new Bla it’s only one object allocatedclass Bla {
val x = 1
val bla = { y -> x }
}
that allocates two objects per instanceval
styleJakub Pi
03/26/2020, 2:57 PMpakoito
03/26/2020, 2:57 PMfun
and take a function reference when it’s neededJakub Pi
03/26/2020, 2:58 PMpakoito
03/26/2020, 3:02 PMWhat I tried to run the whole thing as a sequence I got stackoverflow errors since everything was lazyloool I missed this
Jakub Pi
03/26/2020, 3:08 PMpakoito
03/26/2020, 4:10 PM