0

Could it be possible to write in FFL a version of filter that stops filtering after the first negative match, i.e. the remaining items are assumed to be positive matches? more generally, a filter.

Example:

removeMaxOf1([1,2,3,4], value>=2)

Expected Result:

[1,3,4]

This seems like something very difficult to write in a pure functional style. Maybe recursion or let could acheive it?

Note: the whole motivation for this question was hypothesizing about micro-optimizations. so performance is very relevant. I am also looking for something that is generally applicable to any data type, not just int.

Patrick Parker
  • 4,863
  • 4
  • 19
  • 51

2 Answers2

1

Of course recursion can! :D

filterMaxOf1(input, target)
where filterMaxOf1 = def
        ([int] l, function f) -> [int]
        if(size(l) = 0,
                [],
                if(not f(l[0]),
                        l[1:],
                        flatten([
                                l[0],
                                recurse(l[1:], f)
                        ])
                )
        )
where input = [
        1, 2, 3, 4, ]
where target = def
        (int i) -> bool
        i < 2

Some checks:

--> filterOfMax1([1, ]) where filterOfMax1 = [...]
[1]
--> filterOfMax1([2, ]) where filterOfMax1 = [...]
[]
--> filterOfMax1([1, 2, ]) where filterOfMax1 = [...]
[1]
--> filterOfMax1([1, 2, 3, 4, ]) where filterOfMax1 = [...]
[1, 3, 4]

This flavor loses some strong type safety, but is nearer to tail recursion:

filterMaxOf1(input, target)
where filterMaxOf1 = def
        ([int] l, function f) -> [int]
        flatten(filterMaxOf1i(l, f))
where filterMaxOf1i = def
        ([int] l, function f) -> [any]
        if(size(l) = 0,
                [],
                if(not f(l[0]),
                        l[1:],
                        [
                                l[0],
                                recurse(l[1:], f)
                        ]
                )
        )
where input = [
        1, 2, 3, 4, ]
where target = def
        (int i) -> bool
        i < 2
1737973
  • 159
  • 18
  • 42
  • I made a mistake in my question. it should say `value < 2` for the condition. maybe I should have called it removeMaxOf1 for condiition value>1 – Patrick Parker May 23 '18 at 19:53
  • 1
    I edited further - just by adding a well placed `not` starts working for one question or the other. – 1737973 May 23 '18 at 20:01
  • I noticed that flatten does a deep flatten, so this algorithm wouldn't be generally applicable, e.g. if my data values were lists. – Patrick Parker May 24 '18 at 07:17
1

I have recently added find_index to the engine which allows this to be done easily:

if(n = -1, [], list[:n] + list[n+1:])
where n = find_index(list, value<2)
where list = [1,2,3,4]

find_index will return the index of the first match, or -1 if no match is found. There is also find_index_or_die which returns the index of the first match, asserting if none is found for when you're absolutely certain there is an instance in the list.

You could also implement something like this using recursion:

def filterMaxOf1(list ls, function(list)->bool pred, list result=[]) ->list
base ls = []: result
base not pred(ls[0]): result + ls[1:]
recursive: filterMaxOf1(ls[1:], pred, result + [ls[0]])
Patrick Parker
  • 4,863
  • 4
  • 19
  • 51
Denivarius
  • 181
  • 2