How to use locale_sort/2?

19 views
Skip to first unread message

Jan Burse

unread,
May 15, 2015, 3:22:24 PM5/15/15
to swi-p...@googlegroups.com
Hi,

How can use locale_sort/2? I want to do something along
the following lines:

?-  locale_sort([sin,peach,péché,pêche],X).
X = [peach, péché, pêche, sin].
?- set_locale(fr).
?- locale_sort([sin,peach,péché,pêche],X).
X = [peach, pêche, péché, sin].

But I get stuck in the set_locale/1 statement. This
throws an exception.

And I can't figure out how I could define a collation
via locale_create/3.

Bye

Jan Wielemaker

unread,
May 17, 2015, 4:31:00 AM5/17/15
to Jan Burse, swi-p...@googlegroups.com
Hi Jan,

On 15-05-15 21:22, Jan Burse wrote:
> Hi,
>
> How can use locale_sort/2? I want to do something along
> the following lines:
>
> ?- locale_sort([sin,peach,péché,pêche],X).wot
> X = [peach, péché, pêche, sin].
> ?- set_locale(fr).
> ?- locale_sort([sin,peach,péché,pêche],X).
> X = [peach, pêche, péché, sin].
>
> But I get stuck in the set_locale/1 statement. This
> throws an exception.
>
> And I can't figure out how I could define a collation
> via locale_create/3.

If you read between the lines, you'll get some hint that
set_locale/1 belongs to a special group of predicates that
deal with formatting numbers :-( The thing you are looking
for this setlocale/3, which maps directly to the OS setlocale()
function and controls collation, character types and time
formatting. Unfortunately, setlocale/3 is system-wide, i.e.,
it affects all threads.

So, you should be able to change sorting using e.g.,

setlocale(collate, Old, fr)

provided the locale 'fr' is known on your system (on Unix,
using the command `locale -a` to find the names of known
locales. No clue on Windows).

Cheers --- Jan

Jan Burse

unread,
May 17, 2015, 5:14:11 AM5/17/15
to swi-p...@googlegroups.com, burs...@gmail.com
Ok, I see, I didn't find the setlocale/3 predicate.
Wasn't expecting it in a module shell, but since
its effect is process wide, yeah. I will do some
testing.

BTW: The threading issue could be solved by
having a locale object also for collation etc..
i.e. having variants of the predicates with an
additional parameter.

Since for example on the Windows platform
I find that there is not only wcsxfrm but also
wcsxfrm_l.
https://msdn.microsoft.com/en-us/library/b33a6766.aspx

So that I could call locale_sort(fr,...,...). Instead
of going around with settings. An additional
parameter approach is not only useful for
threading, also take the following scenarios:

1) Web application that serves different
    languages, running in the same process,
    so lets say one page should display results
    in German, and another page should display
    results in English.

2) Standalone applicate that has in itself
    multi-lingual content, for example display
    a table with a German column and an
    English column.

3) SWISH, assume it runs in one process,
    assume you would like to serve German
    users differently from English users.
    Like for example different error messages.

Affected would not be only locale_sort/2 and
collation_key/2, but also format/2 and friends.
All would need additional parameters.

Not sure how you would solve print_message/2.
Since it is Prolog driven. Anyway, some might
view the locale thing a nightmare anyway, others
might see it an interessting challenge.

Jan Burse

unread,
May 17, 2015, 5:22:26 AM5/17/15
to swi-p...@googlegroups.com
Hi,


Am Sonntag, 17. Mai 2015 11:14:11 UTC+2 schrieb Jan Burse:
Since for example on the Windows platform
I find that there is not only wcsxfrm but also
wcsxfrm_l.
https://msdn.microsoft.com/en-us/library/b33a6766.aspx

Such routines are usually lock free, thats actually
the main advantage. You don't have to do:

   with_mut
ex(
        setlocale(collate,NewLocale, OldLocale),
        locale_sort(X,Y),
        setlocale(collate,OldLocale,_))

You can instead do:

        local_sort(NewLocale,X,Y).

But the routines with the additional parameter
might repeat some internal locale lookup, so
that they might be slightly slower. But they
will not slowdown other threads.

Bye

Jan Wielemaker

unread,
May 17, 2015, 6:00:57 AM5/17/15
to Jan Burse, swi-p...@googlegroups.com
On 17-05-15 11:14, Jan Burse wrote:
> Ok, I see, I didn't find the setlocale/3 predicate.
> Wasn't expecting it in a module shell, but since
> its effect is process wide, yeah. I will do some
> testing.

It isn't the most brilliant place. Well, it is not
a module, just a section of the manual and it is titled
"Operating System Interaction". For a long time it was
the only locale related functionality.

> BTW: The threading issue could be solved by
> having a locale object also for collation etc..
> i.e. having variants of the predicates with an
> additional parameter.
>
> Since for example on the Windows platform
> I find that there is not only wcsxfrm but also
>
> wcsxfrm_l.
>
> https://msdn.microsoft.com/en-us/library/b33a6766.aspx

Thanks. Seems this function is now widely enough supported.

> So that I could call locale_sort(fr,...,...). Instead
> of going around with settings. An additional
> parameter approach is not only useful for
> threading, also take the following scenarios:
>
> 1) Web application that serves different
> languages, running in the same process,
> so lets say one page should display results
> in German, and another page should display
> results in English.
>
> 2) Standalone applicate that has in itself
> multi-lingual content, for example display
> a table with a German column and an
> English column.
>
> 3) SWISH, assume it runs in one process,
> assume you would like to serve German
> users differently from English users.
> Like for example different error messages.

I'm not really sure whether an extra parameter makes
sense. For the numeric formatting, it was notably
Richard's suggesting to connect the locale to streams
and set the initial value from the calling thread. Of
course, sorting is not connected to a stream, so that
doesn't work. A thread-local notion of the locale might
suffice though. Web applications and in general
server applications are a typical use-case for which
setting the locale at the level of threads is appropriate.
Ok, if you want a table with German and French formatted
data in different columns you need a bit of switching.

> Affected would not be only locale_sort/2 and
> collation_key/2, but also format/2 and friends.
> All would need additional parameters.

Notable for format that gets ugly as we already have
format/1, format/2 and format/3 :-(

> Not sure how you would solve print_message/2.
> Since it is Prolog driven. Anyway, some might
> view the locale thing a nightmare anyway, others
> might see it an interessting challenge.

I don't think we'd like to go for gettext(). Our
mapping from terms to strings using DCGs is much
nicer. The message infrastructure is modelled after
Quintus, but does not support the Quintus multi
lingual functionality. I think that worked by
loading an appropriate file though and that would
not suffice for servers that wish to server messages
in different languages.

I don't know how useful it is to go that way. First
of all, it requires people willing to add translations.
But still, all names and documentation is English only.
It does make sense for applications that wish to report
low-level errors such as file related errors to the user.

Anyway, no hurry. It is good to know there is improving
support from the C library to make this feasible.

Cheers --- Jan
Reply all
Reply to author
Forward
0 new messages