bug#24186: setlocale can't be localised
Ludovic Courtes wrote: >That wouldn't help with the "setlocale" issue you describe per se, but >this would address such use cases in a different way. > >WDYT? Yes, explicit locale objects and locale parameters to relevant functions are a good thing. In general, the model of a global locale state is broken, at least by threading, so some advance beyond the setlocale system is necessary. Note the new(er) "uselocale" system in libc, which gives a per-thread locale state, fixing the biggest problem with setlocale. Some form of that could also be mapped into Guile; it would be reasonable to have a fluid that determines the locale to use where not overridden by an explicit parameter. All of that is welcome, but, as you say, doesn't deal with the actual problem I identified with setlocale. One can expect that setlocale will continue to be used for the foreseeable future, and it needs to be shorn of its unwanted side effects. -zefram
bug#24186: setlocale can't be localised
Hi, Zeframskribis: > (define (call-with-locale cat val body) > (let ((oldval #f)) > (dynamic-wind > (lambda () (set! oldval (setlocale cat)) (setlocale cat val)) > body (lambda () (setlocale cat oldval) > > (define (day-of-week-string) > (strftime "%A" (localtime (current-time > > (define (day-of-week-string-for-locale loc) > (call-with-locale LC_TIME loc day-of-week-string)) > > ;; user-locale is application-specific code defined elsewhere > (define (day-of-week-string-for-user user) > (day-of-week-string-for-locale (user-locale user))) This does not really answer your question, but (ice-9 i18n) provides first-class locale objects, which avoid the whole global locale issue (info "(guile) Internationalization"). Currently important procedures such as ‘strftime’ or SRFI-19’s ‘date->string’ cannot use such locale objects, though. I think it would make sense to add an optional locale object argument to ‘srftime’ and ‘date->string’ (though we should create a (srfi srfi-19 gnu) module for that to make it clear that this is a GNU extension.) That wouldn’t help with the ‘setlocale’ issue you describe per se, but this would address such use cases in a different way. WDYT? Ludo’.
bug#24186: setlocale can't be localised
On Tue 09 Aug 2016 14:15, Zeframwrites: > I wrote: >>is my first time compiling a Guile myself. It's failing on a missing >>library for which Debian supplies no package. > > Turns out there was a package. It was complaining about a lack of > "bdw-gc", and Debian doesn't have anything of that name, but it does > have it under the name "libgc". So I've now got 2.1.3 running. > > All of the code in my day-of-week-string-for-locale sketch works exactly > the same on 2.1.3 as it did on 2.0. Tx for this testing and thanks again for these excellent bug reports :) Andy
bug#24186: setlocale can't be localised
I wrote: >is my first time compiling a Guile myself. It's failing on a missing >library for which Debian supplies no package. Turns out there was a package. It was complaining about a lack of "bdw-gc", and Debian doesn't have anything of that name, but it does have it under the name "libgc". So I've now got 2.1.3 running. All of the code in my day-of-week-string-for-locale sketch works exactly the same on 2.1.3 as it did on 2.0. -zefram
bug#24186: setlocale can't be localised
Greets :) Firstly, just to make sure that we are getting things right in 2.2 (and if not we need to know), would you mind testing with the latest 2.1.x release? Also, do you have a concrete program whose behavior you expect to be different? I appreciate the call-with-locale example but I'm not sure what is going wrong so having an example invocation would be useful. On Mon 08 Aug 2016 18:32, Zeframwrites: > The setlocale *write* operation also affects port encoding (actually > the default port encoding fluid and the encoding of currently-selected > ports), and that seems to be an intentional change, but it also breaks > the above code. I believe that the intention (for better or for worse) is that calling `setlocale' with 2 arguments changes the "default port encoding". Like, the next port you open will have the encoding specified by the `setlocale', if you don't change it explicitly later. But I don't think it should change the encoding of already-open ports, should it? Andy
bug#24186: setlocale can't be localised
In Guile 1.8 it was possible to localise the effect of a setlocale operation, but in Guile 2.0 it's no longer possible by natural use of the locale API. This loss of a useful facility is either a bug or something that needs to be discussed in the documentation. In Guile 1.8 one could perform a temporary setlocale for the execution of some piece of code, and revert its effect by another setlocale on unwind. This looks like: (define (call-with-locale cat newval body) (let ((oldval #f)) (dynamic-wind (lambda () (set! oldval (setlocale cat)) (setlocale cat newval)) body (lambda () (setlocale cat oldval) Some difficulty arises from this being temporally scoped, where dynamic or lexical scoping would be nicer, but in single-threaded programs it works pretty well. The C setlocale(3) API, after which Guile's setlocale is modelled, is obviously designed to enable this kind of mechanism: the read operation reports all relevant state, and the write operation with the old value sets it all back as it was. It is critical to this ability that the read operation does indeed report all the state that will be set. In Guile 2.0, the setlocale function no longer corresponds so closely to the C setlocale(3), and this critical guarantee has been lost. I have previously reported in bug#22910 that the setlocale read operation has a side effect on port encoding, and obviously that interferes with the above code, but actually there's still a problem if that's fixed. The setlocale *write* operation also affects port encoding (actually the default port encoding fluid and the encoding of currently-selected ports), and that seems to be an intentional change, but it also breaks the above code. The setlocale read operation doesn't report the encoding of the currently-selected ports, so doesn't represent everything that setlocale will set. The setlocale write operation is not even capable of setting the port encodings independently: it sets all three to the encoding nominated by the locale selected for LC_CTYPE purposes. I think adding this extra effect to setlocale was a mistake. It doesn't fit the locale API. If the extra effect is removed, that would resolve this problem. If you really want setlocale to have this effect, then something needs to be done to address the ability that has been lost. The documentation certainly needs to describe the effect on port encoding, which it currently doesn't. (There is a mention of some interaction with the %default-port-encoding fluid in the documentation of that fluid, but it doesn't match reality: it doesn't say that setlocale writes to the fluid.) It also ought to specifically warn that the setlocale save-and-restore dance that works in C doesn't work here. It should explain what needs to be done by library functions that want to achieve a localised locale change. Are they entirely forbidden to use setlocale? Are they expected to manually save and restore port encodings around setlocale calls? (This is complicated by set-port-encoding! not accepting #f as an encoding value, despite it actually being a permitted value for the encoding slot.) Some example code equivalent to the above call-with-locale would be useful. -zefram