# Freeze(\_, Goal) ignores Goal

**URL:** <https://swi-prolog.discourse.group/t/freeze-goal-ignores-goal/6138>\
**Category:** Discussion\
**Created:** [January 27, 2023, 7:53pm UTC](https://swi-prolog.discourse.group/t/freeze-goal-ignores-goal/6138 "2023-01-27T19:53:47Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![brebs](https://avatars.discourse-cdn.com/v4/letter/b/e9c0ed/32.png) [@brebs](https://swi-prolog.discourse.group/u/brebs)\
**Post date:** [January 27, 2023, 7:53pm UTC](https://swi-prolog.discourse.group/t/freeze-goal-ignores-goal/6138/1 "2023-01-27T19:53:47Z")

</div>

Hi, freeze/2 and when/2 seem to have the same problem, with `_` (an anonymous variable):

In SWI-Prolog (threaded, 64 bits, version 9.0.3), running in Void Linux:

```prolog
?- freeze(F, N=1).
freeze(F, N=1). % As expected

?- freeze(_, N=1).
true. % Bad - ignores Goal

```

```prolog
?- when(nonvar(F), N=1).
when(nonvar(F), N=1). % As expected

?- when(nonvar(_), N=1).
true. % Bad - ignores goal

```

My use-case is:

```prolog
max_member_freeze(Max, [H|T]) :-
    ( T == []
        % Only 1 element
    -> Max = H
        % Start with Upto unknown
    ; freeze(H, max_member_freeze_([H|T], _, Max))
    ).

max_member_freeze_([], Max, Max). 
max_member_freeze_([H|T], Upto, Max) :-
    (var(Upto) -> Upto = H ; true),
    when((nonvar(H), nonvar(Upto)),
        ( (nonvar(Max) -> Max @>= H ; true),
            max(H, Upto, Upto1),
            freeze(T, max_member_freeze_(T, Upto1, Max))
        )
    ).

max(X, Y, Max) :-
    ( X @< Y
    -> Max = Y
    ; Max = X
    ).  

```

… which gives:

```prolog
?- max_member_freeze(1, [1, N]).
when(nonvar(N), ((nonvar(1)->1@>=N;true), max(N, 1, _A), freeze([], max_member_freeze_([], _A, 1)))).
% As expected

```

```prolog
?- max_member_freeze(1, [1, _]).
true. % Wrongly ignores the potential value of the 2nd element in the list

```

Is this a bug? Shouldn’t `_` be converted by the system into a variable such as `_A`?

Perhaps this is a useful trick, to “prevent” an anonymous variable:

```prolog
?- _ = f(F), freeze(F, N=1).
freeze(F, N=1).

```

… or is there some workaround?

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [January 27, 2023, 8:23pm UTC](https://swi-prolog.discourse.group/t/freeze-goal-ignores-goal/6138/2 "2023-01-27T20:23:40Z")

</div>

> [@brebs](#):
>
> `?- freeze(_, N=1).`

I suspect that this is a “feature” (or “bug”) of how results are printed (after all, the output `freeze(F,N=1)` is a kind of `true`; it’s just printed with some extra context). If you query `freeze(_A,N=1)`, you get the expected result, similarly with `max_member_freeze(1, [1, _N])`.

---

<div class="post-metadata">

**Author:** ![brebs](https://avatars.discourse-cdn.com/v4/letter/b/e9c0ed/32.png) [@brebs](https://swi-prolog.discourse.group/u/brebs)\
**Post date:** [January 27, 2023, 8:35pm UTC](https://swi-prolog.discourse.group/t/freeze-goal-ignores-goal/6138/3 "2023-01-27T20:35:43Z")

</div>

Thanks, yes that looks likely - this shows the fuller picture:

```prolog
?- call_residue_vars(max_member_freeze(1, [1, _]), Vs).
Vs = [_A],
when(nonvar(_A), ((nonvar(1)->1@>=_A;true), max(_A, 1, _B), freeze([], max_member_freeze_([], _B, 1)))).

```
