Hi,

it's ITO Friday again. I still have an improved patch for the reduce
function (http://en.wikipedia.org/wiki/Reduce_%28higher-order_function%29)
lying around (see attachment). It adds two versions of the function:

1) One that takes an initial value.

    integer sum = list::reduce(integer x, integer y, 0, [ 1, 2, 3 ], { return x 
+ y; });
    integer product = list::reduce(integer x, integer y, 1, [ 1, 2, 3 ], { 
return x * y; })

2) One were the initial value is the value of the first list entry. Here
   the list must of course have at least one entry.

    integer min = list::reduce(integer x, integer y, [ 1, 2, 3 ], { return x < 
y ? x : y; });
    integer max = list::reduce(integer x, integer y, [ 1, 2, 3 ], { return x > 
y ? x : y; });

The behaviour is now analogous to Python's reduce so it shouldn't be
completely screwed. The patch contains no binary incompatibility to libycp
or the bytecode.

Please comment.

ciao Arvin

Index: YCPBuiltinList.cc
===================================================================
--- YCPBuiltinList.cc	(revision 48433)
+++ YCPBuiltinList.cc	(working copy)
@@ -1083,6 +1083,121 @@
 
 
 static YCPValue
+l_reduce1 (const YCPSymbol &x, const YCPSymbol &y, const YCPList &list, const YCPCode &expr)
+{
+    /**
+     * @builtin list::reduce
+     * @id reduce_1
+     * @short Reduces a list to a single value.
+     * @param flex1 x
+     * @param flex1 y
+     * @param list<flex1> list
+     * @param block<flex1> expr
+     * @return flex1
+     *
+     * TODO
+     */
+
+    if (list.isNull())
+    {
+	return YCPNull();
+    }
+
+    if (list->size() < 1)
+    {
+	ycp2error("Bad list %s for 'reduce'", list->toString().c_str());
+	return YCPNull();
+    }
+
+    SymbolEntryPtr xs = x->asEntry()->entry();
+    SymbolEntryPtr ys = y->asEntry()->entry();
+
+    YCPValue ret = list->value(0);
+
+    for (int i = 1; i < list->size(); i++)
+    {
+	xs->setValue(ret);
+	ys->setValue(list->value(i));
+
+	YCPValue tmp = expr->evaluate();
+	if (tmp.isNull())
+	{
+	    ycp2error("Bad 'reduce' expression %s", expr->toString().c_str());
+	    continue;
+	}
+	if (tmp->isVoid())
+	{
+	    ycp2error("The expression for 'reduce' returned 'nil'");
+	    continue;
+	}
+	if (tmp->isBreak())
+	{
+	    break;
+	}
+
+	ret = tmp;
+    }
+
+    return ret;
+}
+
+
+static YCPValue
+l_reduce2 (const YCPSymbol &x, const YCPSymbol &y, const YCPValue &initial, const YCPList &list, const YCPCode &expr)
+{
+    /**
+     * @builtin list::reduce
+     * @id reduce_2
+     * @short Reduces a list to a single value.
+     * @param flex1 x
+     * @param flex2 y
+     * @param flex1 value
+     * @param list<flex2> list
+     * @param block<flex1> expr
+     * @return flex1
+     *
+     * TODO
+     */
+
+    if (list.isNull())
+    {
+	return YCPNull();
+    }
+
+    SymbolEntryPtr xs = x->asEntry()->entry();
+    SymbolEntryPtr ys = y->asEntry()->entry();
+
+    YCPValue ret = initial;
+
+    for (int i = 0; i < list->size(); i++)
+    {
+	xs->setValue(ret);
+	ys->setValue(list->value(i));
+
+	YCPValue tmp = expr->evaluate();
+	if (tmp.isNull())
+	{
+	    ycp2error("Bad 'reduce' expression %s", expr->toString().c_str());
+	    continue;
+	}
+	if (tmp->isVoid())
+	{
+	    ycp2error("The expression for 'reduce' returned 'nil'");
+	    continue;
+	}
+	if (tmp->isBreak())
+	{
+	    break;
+	}
+
+	ret = tmp;
+    }
+
+    return ret;
+}
+
+
+static YCPValue
 l_tolist (const YCPValue &v)
 {
     /**
@@ -1143,5 +1258,14 @@
 	{ 0 }
     };
 
+    // must be static, registerDeclarations saves a pointer to it!
+    static declaration_t declarations_ns[] = {
+	{ "list",	"",											NULL,	                DECL_NAMESPACE },
+	{ "reduce",	"flex1 (variable <flex1>, variable <flex1>, const list <flex1>, const block <flex1>)",  (void *)l_reduce1, DECL_LOOP|DECL_SYMBOL|DECL_FLEX },
+	{ "reduce",	"flex1 (variable <flex1>, variable <flex2>, const flex1, const list <flex2>, const block <flex1>)", (void *)l_reduce2, DECL_LOOP|DECL_SYMBOL|DECL_FLEX },
+	{ 0 }
+    };
+
     static_declarations.registerDeclarations ("YCPBuiltinList", declarations);
+    static_declarations.registerDeclarations ("YCPBuiltinList", declarations_ns);
 }

Reply via email to