# Composing an arithmetic function in a loop (but without univ)

**URL:** <https://swi-prolog.discourse.group/t/composing-an-arithmetic-function-in-a-loop-but-without-univ/9593>\
**Category:** General\
**Created:** [May 4, 2026, 11:47am UTC](https://swi-prolog.discourse.group/t/composing-an-arithmetic-function-in-a-loop-but-without-univ/9593 "2026-05-04T11:47:46Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![stassa.p](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/stassa.p/32/712_2.png) [@stassa.p](https://swi-prolog.discourse.group/u/stassa.p)\
**Post date:** [May 4, 2026, 11:47am UTC](https://swi-prolog.discourse.group/t/composing-an-arithmetic-function-in-a-loop-but-without-univ/9593/1 "2026-05-04T11:47:46Z")

</div>

The title is not very descriptive, I know. I was trying to code-golf the shortest Prolog program I could think of to sum a a list of integers. I came up with this:

```prolog
solve([],S,S).
solve([N|Ns],S0,Acc):-
        solve(Ns,N+S0,Acc).

```

Which can then be called as follows, delegating the execution of the addition operations to the top-level:

```prolog
45 ?- _Ls = [1,2,3], user:solve(_Ls,0,S), S_ is S.
S = 3+(2+(1+0)),
S_ = 6.

```

So far, so Prolog-y and I thought that’s a nice trick because it exposes Prolog’s internal workings, i.e how it does not “derference” functions and how everything is a term etc.

Then I thought why not generalise this so that the operator is passed to the solve predicate so that it can then do arbitrary operations on integers? Something like apply-list etc. So I tried this:

```prolog
solve([],_,S,S).
solve([N|Ns],Op,S0,Acc):-
        solve(Ns,(N,Op,S0),Acc).

```

And immediately I was stumped by the behaviour of the runtime which seems to treat the first interpretation of the operator, stored in the argument `Op` differently than every subsequent interpretation of the same operator:

```prolog
47 ?- _Ls = [1,2,3], _Op = +, user:solve(_Ls,_Op,0,S).
S = 3+(2+(1, (+), 0)).

```

Here’s the trace of the top-level query:

```prolog
[debug] 49 ?- _Ls = [1,2,3], _Op = +, user:solve(_Ls,_Op,0,S).
   Call: (15) solve([1, 2, 3], +, 0, _23890) ? leap
   Call: (16) solve([2, 3], (1, (+), 0), _23890) ? leap
   Call: (17) solve([3], 2+(1, (+), 0), _23890) ? leap
   Call: (18) solve([], 3+(2+(1, (+), 0)), _23890) ? leap
   Exit: (18) solve([], 3+(2+(1, (+), 0)), 3+(2+(1, (+), 0))) ? leap
   Exit: (17) solve([3], 2+(1, (+), 0), 3+(2+(1, (+), 0))) ? leap
   Exit: (16) solve([2, 3], (1, (+), 0), 3+(2+(1, (+), 0))) ? leap
   Exit: (15) solve([1, 2, 3], +, 0, 3+(2+(1, (+), 0))) ? leap
S = 3+(2+(1, (+), 0)).

```

Note that the end result here is not a valid arithmetic function, so this raises an error:

```prolog
52 ?- _Ls = [1,2,3], _Op = -, user:solve(_Ls,_Op,0,S), S_ is S.
ERROR: Arithmetic: `(-)/0' is not a function
ERROR: In:
ERROR: [15] _52778 is 3+(2+ ...)
ERROR: [13] toplevel_call(user:user: ...) at c:/program files/swipl/boot/toplevel.pl:1529
ERROR: 
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.

```

So what’s going on here? Why is the result of the first `(N, Op, 0)` different than any subsequent one, and how is it different? Is this an expansion hook? I never use those so I’m not even sure where to look for it.

Btw just to be clear: the point is not the code golf anymore, nor even to compose an arithmetic function which I reckon I could do with univ without trouble, I’m just trying to figure out what’s going on with this weird syntactic quirk of Prolog that I hadn’t noticed before. Happens every few years 🙂

---

<div class="post-metadata">

**Author:** ![ridgeworks](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/ridgeworks/32/886_2.png) [@ridgeworks](https://swi-prolog.discourse.group/u/ridgeworks)\
**Post date:** [May 4, 2026, 2:03pm UTC](https://swi-prolog.discourse.group/t/composing-an-arithmetic-function-in-a-loop-but-without-univ/9593/2 "2026-05-04T14:03:04Z")

</div>

> [@stassa.p](#):
>
> So I tried this:
> 
> ```prolog
> solve([],_,S,S).
> solve([N|Ns],Op,S0,Acc):-
> solve(Ns,(N,Op,S0),Acc).
> 
> ```

Your `solve/4` predicate’s recursive call is to `solve/3`. If your first `solve/3` implementation is visible it explains the behaviour.

---

<div class="post-metadata">

**Author:** ![Olopierpa](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/olopierpa/32/6855_2.png) [@Olopierpa](https://swi-prolog.discourse.group/u/Olopierpa)\
**Post date:** [May 4, 2026, 2:33pm UTC](https://swi-prolog.discourse.group/t/composing-an-arithmetic-function-in-a-loop-but-without-univ/9593/3 "2026-05-04T14:33:35Z")

</div>

solve(,\_,S,S).  
solve([N|Ns],Op,S0,Acc):-  
Expr =.. [Op,N,S0],  
solve(Ns,Op,Expr,Acc).

?- solve([1,2,3],+,0,S).  
S = 3+(2+(1+0)).  
?- solve([1,2,3],_,1,S).  
S = 3_(2\*(1\*1)).

You want this? 🙂

---

<div class="post-metadata">

**Author:** ![Olopierpa](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/olopierpa/32/6855_2.png) [@Olopierpa](https://swi-prolog.discourse.group/u/Olopierpa)\
**Post date:** [May 4, 2026, 2:36pm UTC](https://swi-prolog.discourse.group/t/composing-an-arithmetic-function-in-a-loop-but-without-univ/9593/4 "2026-05-04T14:36:37Z")

</div>

Sorry, I had missed the ‘without univ’ in the title.  
Will functor/3 and arg/3 do it?

---

<div class="post-metadata">

**Author:** ![CapelliC](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/capellic/32/17_2.png) [@CapelliC](https://swi-prolog.discourse.group/u/CapelliC)\
**Post date:** [May 4, 2026, 5:09pm UTC](https://swi-prolog.discourse.group/t/composing-an-arithmetic-function-in-a-loop-but-without-univ/9593/5 "2026-05-04T17:09:01Z")

</div>

Seems you’re fighting op/3 syntax…

```prolog
103 ?- X is +(1,+(2,3)).
X = 6.

```

then

```prolog
solve([N],N).
solve([H|T],+(H,R)) :- solve(T,R).

```

yields

```prolog
107 ?- solve([1,2,3],E),X is E.
E = 1+(2+3),
X = 6 .

```

HTH

---

<div class="post-metadata">

**Author:** ![stassa.p](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/stassa.p/32/712_2.png) [@stassa.p](https://swi-prolog.discourse.group/u/stassa.p)\
**Post date:** [May 4, 2026, 6:26pm UTC](https://swi-prolog.discourse.group/t/composing-an-arithmetic-function-in-a-loop-but-without-univ/9593/6 "2026-05-04T18:26:49Z")

</div>

> [@ridgeworks](#):
>
> Your `solve/4` predicate’s recursive call is to `solve/3`. If your first `solve/3` implementation is visible it explains the behaviour.

Thanks. That explains why it looked different:

```prolog
solve([],_,S,S).
solve([N|Ns],Op,S0,Acc):-
        solve(Ns,Op,(N,Op,S0),Acc).

56 ?- _Ls = [1,2,3], _Op = +, user:solve(_Ls,_Op,0,S).
S = (3, (+), 2, (+), 1, (+), 0).

```

> [@CapelliC](#):
>
> Seems you’re fighting [op/3](https://www.swi-prolog.org/pldoc/doc_for?object=op/3) syntax…

Thanks Carlo. I like the arity-2 version. But what I’d really like to be able to do is say Op(H,R), and pass an arbitrary atom to bind to Or, but that’s not valid Prolog.
