[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
RE: sorted?
From: |
Maxime Devos |
Subject: |
RE: sorted? |
Date: |
Thu, 12 Dec 2024 16:40:09 +0100 |
>Doing Advent of Code 2024, I was trying to use `sorted?` procedure. And
something bothered me.
>
>The reference says :
>
> Scheme Procedure: *sorted?* items less
> C Function: *scm_sorted_p* (items, less)
>
> Return |#t| if items is a list or vector such that, for each
> element x and the next element y of items, |(less y x)| returns
> |#f|. Otherwise return |#f|.
>
>I think the description should be :
>
> Return |#t| if items is a list or vector such that, for each element
> x and the next element y of items, |(less y x)| returns |#t|.
> Otherwise return |#f|.
>
It shouldn’t. Let’s start with your example:
>Then, testing it in the REPL give me this :
>
>scheme@(guile-user)> (sorted? '(1 2 3) <)
>$13 = #t
>
>So far so good.
>
>scheme@(guile-user)> (sorted? '(3 2 1) <)
>$16 = #f
Consider the simpler case (sorted? '(1 2) <). This should, and does, return
#true.
In this example, x=1 and y=2. Then, (less y x) is (< 2 1). This evaluates to
#false. Since #false isn’t #true, according to the first description, (sorted?
'(1 2) <) return #true. So, first description is ok in this case! Likewise, it
is ok for (sorted? '(2 1) <).
However, the second description is wrong (just go over it step-by-step again if
needed).
There is also another, more subtle thing going on. Conventionally, all values
are truth values: everything not #false is considered to be ‘true’ (in Guile
Scheme, also #nil is counted like #false I think, not sure). In Scheme, while a
predicate (*) that is exposed (e.g. exported from a module) should produce only
#t or #f as truth values (with some exceptions, like when it would prevent
tail-calls, or when it invokes another caller-provided predicate that produces
other truth values, it doesn’t need to normalise that), it’s usually fine for a
predicate supplied by the caller (‘less’, in this case) to produce other truth
values.
Because of that reason, it needs to be phrased in terms of #false instead of
#true (actually #false->false, to account for #nil).
(*) in a general sense, also including multiple-variable relations.
>scheme@(guile-user)> (sorted? '(1 1) <)
$17 = #t
>I was expecting #f due to
>scheme@(guile-user)> (< 1 1)
>$18 = #f
By the second description, sure.
But by the first description, it is fine!
My guess is that it’s intentional, so that you can save one keystroke to write
(sorted? '(1 1) <) instead of (sorted? '(1 2) <=).
Although, the description could use a bit of expansion to make clear what
happens in the case that two elements are equal, and put emphasis on it really
being ‘less’, not ‘less-than-or-equal-to’.
Best regards,
Maxime Devos
- Re[2]: sorted?, (continued)
- Re[2]: sorted?, Stefan Schmiedl, 2024/12/09
- Re: sorted?, tomas, 2024/12/09
- Re: sorted?, Mikael Djurfeldt, 2024/12/09
- Re: sorted?, Mikael Djurfeldt, 2024/12/09
- Re: sorted?, tomas, 2024/12/09
- Re: sorted?, Mikael Djurfeldt, 2024/12/09
- RE: sorted?, Maxime Devos, 2024/12/12
- RE: sorted?, Maxime Devos, 2024/12/12
- RE: sorted?, Maxime Devos, 2024/12/12
- RE: sorted?, Maxime Devos, 2024/12/12
RE: sorted?,
Maxime Devos <=