Forums

support for reduce in query language?

General discussion about Cobra. Releases and general news will also be posted here.
Feel free to ask questions or just say "Hello".

support for reduce in query language?

Postby kobi7 » Thu Dec 12, 2013 12:38 am

Hi,
Is there support for something like reduce or aggregate in the
for syntax?
for example
for p in plants reduce ( (p1,p2 ) p1.radius < p2.radius ) get p1
or something similar.
in other words, have a function that takes two items, and returns one.
This can be implemented as
p1 = plants[0]
for p in plants
if p.radius < p1.radius
p1 = p
return p1

maybe return nil if the list is empty?
Falun Dafa is Good.
Truth, Compassion, Forbearance is Good.
kobi7
 
Posts: 82
Location: Israel

Re: support for reduce in query language?

Postby ObtuseAngle » Thu Dec 12, 2013 4:54 pm

Here's a simple starting point:

Code: Select all
class TestReduce

    sig SomeReducingFunction(a as int, b as int) as int

    def lesser(a as int, b as int) as int
        if a < b
            return a
        else
            return b

    def reduce(aList as List<of int>, aReducingFunction as SomeReducingFunction, initialValue as int) as int
        result = initialValue
        for item in aList
            result = aReducingFunction(item, result)
        return result


    def main
        i = 5
        myList = [3, 4, 5, 6, 7]
        reducingFunction as SomeReducingFunction = ref .lesser
        print .reduce(myList, reducingFunction, i)
99 programming bugs in the code, 99 bugs in the code, fix 1 bug and compile it again, 101 programming bugs in the code
ObtuseAngle
 
Posts: 42
Location: Gippsland, Australia

Re: support for reduce in query language?

Postby Charles » Thu Dec 12, 2013 6:57 pm

Thanks ObtuseAngle. Here is a slight evolution which allows the initial value to be unspecified provided the list has at least one element. I also separated out the delegate and utility method similar to what I would do in an actual application:

EDIT: And I changed the type from List<of int> to IList<of int>.

sig ReducingFunction(a as int, b as int) as int

class Utils

shared

def reduce(list as IList<of int>, func as ReducingFunction, initialValue as int? = nil) as int
require initialValue is not nil or list.count > 0
result = initialValue ? list[0]
for item in list, result = func(item, result)
return result


class TestReduce

def lesser(a as int, b as int) as int
if a < b, return a
else, return b

def main
i = 5
myList = [4, 5, 3, 6, 7]
# can use like this:
reducingFunction as ReducingFunction = ref .lesser
print Utils.reduce(myList, reducingFunction, i)
# or simply:
print Utils.reduce(myList, ReducingFunction(ref .lesser), i)
# and without an initial value passed in:
print Utils.reduce(myList, ref .lesser) == 3
Charles
 
Posts: 2515
Location: Los Angeles, CA

Re: support for reduce in query language?

Postby Charles » Thu Dec 12, 2013 7:43 pm

And now a generic version with tests for ints and strings. I made it an extension method so you can slap a ".reduce" on any list you refer to. I also added an example of specifying the reduction function "inline" with the "do" feature.

I really wouldn't have gotten to this tonight if ObtuseAngle hadn't gotten it started. I became obsessed. "That has to be made generic!" :D

Enjoy!

extend IList<of T>

def reduce(func as Func<of T, T, T>) as T
require .count > 0
result = this[0]
for i in 1 : .count, result = func(result, this[i])
return result

def reduce(func as Func<of T, T, T>, initialValue as T) as T
result = initialValue
for item in this, result = func(result, item)
return result


class TestReduce

shared

def lesser(a as int, b as int) as int
if a < b, return a
else, return b

def greater(a as String, b as String) as String
if a.toLower > b.toLower, return a
else, return b

def main
.testString
.testInt

def testString
names = ['m', 'z', 'a', 'b']

# example: refer to a method for reducing
last = names.reduce(ref .greater)
assert last == 'z'

# example: inline the reduction method
last = names.reduce(do(a as String, b as String))
if a.toLower > b.toLower, return a
else, return b
assert last == 'z'

def testInt
i = 50_000
myList = [4, 5, 3, 6, 7]

# example A
j = myList.reduce(ref .lesser)
assert j == 3

# example B
j = myList.reduce(ref .lesser, i)
assert j == 3

# example C
func as Func<of int, int, int> = ref .lesser
j = myList.reduce(func, i)
assert j == 3
Charles
 
Posts: 2515
Location: Los Angeles, CA

Re: support for reduce in query language?

Postby ObtuseAngle » Thu Dec 12, 2013 10:54 pm

Ooh, I like that list extension - elegant. Thanks for that example!

Inline functions, on the other hand, generally tend to grate on my nerve endings - but that is perhaps a closer solution to kobi7's request.
99 programming bugs in the code, 99 bugs in the code, fix 1 bug and compile it again, 101 programming bugs in the code
ObtuseAngle
 
Posts: 42
Location: Gippsland, Australia

Re: support for reduce in query language?

Postby kobi7 » Sat Dec 14, 2013 10:37 am

oooh!! thank you guys!
that's a really nice present :-)

shall I risk my luck with further requests? ;-)
Falun Dafa is Good.
Truth, Compassion, Forbearance is Good.
kobi7
 
Posts: 82
Location: Israel


Return to Discussion

Who is online

Users browsing this forum: No registered users and 47 guests