'Sort By' Function for Rebol I'm looking for a more consise way to sort a block of objects. Where you can sort a block of blocks based on the numeric position of the values to compare, there's no such shorthand for comparing objects by a given field:

test-data: reduce [
    object [name: "A" value: 1]
    object [name: "B" value: 3]
    object [name: "C" value: 2]
]


One solution would be to extend the native SORT function to accept a WORD! argument corresponding to the object field. However, that would require an update to the language and might take a little while to be accepted.

I've sketched out the following SORT-BY function that would take either a word (for the object field) or a block (an expression that is applied to the object):

sort-by: func [series [block!] comparator [block! word!]][
    forskip series 2 [
        insert series either word? comparator [
            all [
                in series/1 :comparator
                get in series/1 :comparator
            ]
        ][
            use [object] compose [
                object: first series
                (comparator)
            ]
        ]
    ]

    sort/skip series 2

    head forall series [remove series]
]


It's not ideal—it iterates through the block pulling the respective value from each object and adding it to the block; sorts the block; and removes the value again.

sort-by test-data 'value
sort-by test-data 'name
sort-by test-data [object/value]
sort-by test-data [sine 50 * object/value]


Any thoughts on the approach, particularly economy? Or even the need for such a function...

Obviously is lacking a descending/ascending switch—implied in future revision.
Any reason you can't use the SORTs /COMPARE refinement here?

Here is a working example of sort-by that uses it:

sort-by: function [
    series     [block!]
    comparator [block! word!]
  ][
    sort/compare series func [`a `b] either word? comparator [
        [`a/:comparator &lt; `b/:comparator]
    ][
        sortie: function [by] [
            s: to-paren copy/deep comparator
            forall s [
                if all [path? s/1  s/1/1 = 'object] [s/1/1: by]
            ]
            s
        ]

        compose [(sortie '`a) &lt; (sortie '`b)]
    ]
]