How to disable character codes 178 (0xB2) (²) , 17

2019-07-06 09:05发布

问题:

With SWI-Prolog when generating digits using

code_type(X,digit).

the result is the expected ASCII character codes and

178 (0xB2) ²
179 (0xB3) ³
185 (0xB9) ¹

e.g.

code_type(X,digit).
X = 48 ;
X = 49 ;
X = 50 ;
X = 51 ;
X = 52 ;
X = 53 ;
X = 54 ;
X = 55 ;
X = 56 ;
X = 57 ;
X = 178 ;
X = 179 ;
X = 185 ;
false.

How can I disable or change the functionality so that characters other than 0-9 are not a digit?

Obviously I can write a different routine, but I am wondering if there is not some option or statement to be executed that can do this.

TL;DR

Version

SWI-Prolog (Multi-threaded, 32 bits, Version 7.2.3)

SWI-Prolog Flags

current_prolog_flag(Name,Value).

query_debug_settings: debug(false,false)

save_history: true

debug: false

generate_debug_info: true

verbose_load: silent

emulated_dialect: swi

sandboxed_load: false

optimise: false

toplevel_var_size: 1000

allow_dot_in_atom: false

toplevel_prompt: ~m~d~l~! ?- 

toplevel_print_anon: true

access_level: user

verbose_autoload: false

toplevel_extra_white_line: true

gui: true

timezone: 18000

verbose_file_search: false

char_conversion: false

history: 25

colon_sets_calling_context: true

verbose: normal

traditional: false

agc_margin: 10000

encoding: text

readline: false

break_level: 0

xpce: true

write_attributes: ignore

answer_format: ~p

quasi_quotations: true

bounded: false

min_tagged_integer: -16777216

integer_rounding_function: toward_zero

gmp_version: 5

xpce_version: 6.6.66

dde: true

gc: true

write_help_with_overstrike: false

user_flags: silent

address_bits: 32

max_tagged_integer: 16777215

allow_variable_name_as_functor: false

editor: pce_emacs

debug_on_error: true

shared_object_extension: dll

xpce_threaded: true

resource_database: c:/program files (x86)/swipl/boot32.prc

debugger_show_context: false

character_escapes: true

shared_object_search_path: PATH

iso: false

large_files: true

debugger_write_options: [quoted(true),portray(true),max_depth(10),attributes(portray),spacing(next_argument)]

pipe: true

c_cflags: 

open_shared_object: true

threads: true

unload_foreign_libraries: false

home: c:/program files (x86)/swipl

prompt_alternatives_on: determinism

system_thread_id: 12492

dialect: swi

pid: 9796

executable: C:\Program Files (x86)\swipl\bin\swipl-win.exe

c_cc: gcc

last_call_optimisation: true

qcompile: false

warn_override_implicit_import: true

unknown: error

c_ldflags: 

print_write_options: [portray(true),quoted(true),numbervars(true)]

c_libs: 

c_libplso: -lswipl

max_arity: unbounded

report_error: true

trace_gc: false

autoload: true

answer_write_options: [quoted(true),portray(true),max_depth(10),spacing(next_argument)]

debug_term_position: false

back_quotes: codes

occurs_check: false

compile_meta_arguments: false

os_argv: [C:\Program Files (x86)\swipl\bin\swipl-win.exe,--win_app]

argv: []

emacs_inferior_process: false

cpu_count: 4

file_name_variables: false

color_term: true

version_data: swi(7,2,3,[])

hwnd: 924196

version_git: 7.2.3

console_menu: true

toplevel_residue_vars: false

double_quotes: string

stream_type_check: loose

windows: true

fileerrors: true

version: 70203

signals: true

arch: i386-win32

toplevel_print_factorized: false

compiled_at: Aug 25 2015, 13:45:56

tty_control: true

SWI-Prolog locale

current_locale(X).
X = default.

locale_property(X,Y).
X = default,
Y = alias(default) ;
X = default,
Y = decimal_point('.') ;
X = default,
Y = thousands_sep(',') ;
X = default,
Y = grouping([repeat(3)]).

Windows

Windows PowerShell

PS C:\>  Get-UICulture

LCID             Name             DisplayName
----             ----             -----------
1033             en-US            English (United States)


PS C:\> Get-CimInstance Win32_OperatingSystem | FL *

Status                                    : OK
Name                                      : Microsoft Windows 10 Pro|C:\WINDOWS|\Device\Harddisk0\Partition4
FreePhysicalMemory                        : 853644
FreeSpaceInPagingFiles                    : 7062504
FreeVirtualMemory                         : 2415552
Caption                                   : Microsoft Windows 10 Pro
InstallDate                               : 8/4/2016 8:35:18 AM
CreationClassName                         : Win32_OperatingSystem
CSCreationClassName                       : Win32_ComputerSystem
CurrentTimeZone                           : -300
LastBootUpTime                            : 1/11/2017 1:41:34 PM
LocalDateTime                             : 1/14/2017 3:48:46 PM
MaxNumberOfProcesses                      : 4294967295
MaxProcessMemorySize                      : 137438953344
OSType                                    : 18
Version                                   : 10.0.14393
BuildNumber                               : 14393
BuildType                                 : Multiprocessor Free
CodeSet                                   : 1252
CountryCode                               : 1
DataExecutionPrevention_32BitApplications : True
DataExecutionPrevention_Available         : True
DataExecutionPrevention_Drivers           : True
DataExecutionPrevention_SupportPolicy     : 2
Debug                                     : False
Locale                                    : 0409
Manufacturer                              : Microsoft Corporation
MUILanguages                              : {en-US}
OperatingSystemSKU                        : 48
Organization                              : Windows User
OSArchitecture                            : 64-bit
OSLanguage                                : 1033
OSProductSuite                            : 256
PortableOperatingSystem                   : False
Primary                                   : True
ProductType                               : 1
ServicePackMajorVersion                   : 0
ServicePackMinorVersion                   : 0
SuiteMask                                 : 272
SystemDirectory                           : C:\WINDOWS\system32
SystemDrive                               : C:
WindowsDirectory                          : C:\WINDOWS

Output

code_type(X,digit).
X = 48 ;
X = 49 ;
X = 50 ;
X = 51 ;
X = 52 ;
X = 53 ;
X = 54 ;
X = 55 ;
X = 56 ;
X = 57 ;
X = 178 ;
X = 179 ;
X = 185 ;
false.

X is 0'².
X = 178.

X is 0'³.
X = 179.

X is 0'¹.
X = 185.

code_type(47,digit).
false.
code_type(48,digit).
true.
code_type(0'0,digit).
true.
code_type(57,digit).
true.
code_type(58,digit).
false.
code_type(0'9,digit).
true.
code_type(177,digit).
false.
code_type(178,digit).
true.
code_type(179,digit).
true.
code_type(180,digit).
false.
code_type(184,digit).
false.
code_type(185,digit).
true.
code_type(186,digit).
false.

char_type(X,digit).
X = '0' ;
X = '1' ;
X = '2' ;
X = '3' ;
X = '4' ;
X = '5' ;
X = '6' ;
X = '7' ;
X = '8' ;
X = '9' ;
X = ² ;
X = ³ ;
X = ¹ ;
false.

What I tried/checked

2.4 Command line options

code_type/2

As char_type/2, but uses character codes rather than one-character atoms. Please note that both predicates are as flexible as possible. They handle either representation if the argument is instantiated and will instantiate only with an integer code or a one-character atom, depending of the version used. See also the Prolog flag double_quotes, atom_chars/2 and atom_codes/2.

char_type/2

Tests or generates alternative Types or Chars.
The character types are inspired by the standard C <ctype.h> primitives.

char_type(?Char, ?Type)

digit - Char is a digit.

2.15.1.8 Unicode Prolog source

The SWI-Prolog Unicode character classification is based on version 6.0.0 of the Unicode standard. Please note that char_type/2 and friends, intended to be used with all text except Prolog source code, is based on the C library locale-based classification routines.

but didn't know how to find C library locale-based classification routines

I did a Google search using swi prolog code_type digit 178 however nothing that explains this shows up.

2.18 Wide character support

SWI-Prolog supports wide characters, characters with character codes above 255 that cannot be represented in a single byte. Universal Character Set (UCS) is the ISO/IEC 10646 standard that specifies a unique 31-bit unsigned integer for any character in any language. It is a superset of 16-bit Unicode, which in turn is a superset of ISO 8859-1 (ISO Latin-1), a superset of US-ASCII. UCS can handle strings holding characters from multiple languages, and character classification (uppercase, lowercase, digit, etc.) and operations such as case conversion are unambiguously defined.

ISO/IEC 10646 - Unicode 6.0

0030;DIGIT ZERO;Nd;0;EN;;0;0;0;N;;;;;
0031;DIGIT ONE;Nd;0;EN;;1;1;1;N;;;;;
0032;DIGIT TWO;Nd;0;EN;;2;2;2;N;;;;;
0033;DIGIT THREE;Nd;0;EN;;3;3;3;N;;;;;
0034;DIGIT FOUR;Nd;0;EN;;4;4;4;N;;;;;
0035;DIGIT FIVE;Nd;0;EN;;5;5;5;N;;;;;
0036;DIGIT SIX;Nd;0;EN;;6;6;6;N;;;;;
0037;DIGIT SEVEN;Nd;0;EN;;7;7;7;N;;;;;
0038;DIGIT EIGHT;Nd;0;EN;;8;8;8;N;;;;;
0039;DIGIT NINE;Nd;0;EN;;9;9;9;N;;;;;
00B2;SUPERSCRIPT TWO;No;0;EN;<super> 0032;;2;2;N;SUPERSCRIPT DIGIT TWO;;;;
00B3;SUPERSCRIPT THREE;No;0;EN;<super> 0033;;3;3;N;SUPERSCRIPT DIGIT THREE;;;;
00B9;SUPERSCRIPT ONE;No;0;EN;<super> 0031;;1;1;N;SUPERSCRIPT DIGIT ONE;;;;

ISO 8859-1 Shows ¹,²,³

US-ASCII

Different versions of Windows OS and/or SWI-Prolog

I also uninstalled the 32-bit version and installed the 64-bit version
SWI-Prolog (Multi-threaded, 64 bits, Version 7.2.3 and still the same result.

I also installed the 64-bit version on a different Windows 10 machine that has never had SWI-Prolog on it and still the same result.

I checked an older version SWI-Prolog (Multi-threaded, 64 bits, Version 6.4.1) running on Windows 7 Ultimate Version 6.1.7601, and still the same result.

Other References

SWI-Prolog source code on GitHub

src/os/pl-ctype.c

This module defines:

    char_type(?Char, ?Type)

    code_type(?Char, ?Type)

Windows-1252

Workaround

Many people are not aware of this as it is still in beta but with Windows 10 64-bit one can run Ubuntu packages and do other Ubuntu things on a Windows subsystem called Bash on Ubuntu on Windows, also know as Windows Subsystem for Linux.

After installing WSL then following the instructions on Installing from PPA (Ubuntu Personal Package Archive) and starting SWI-Prolog, I get the expected output.

findall(C,char_type(C,digit),Cs).
Cs = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'].

回答1:

See the section on locale support. If you run, from the toplevel:

?- current_locale(Locale).

and you get Locale = default, then your current thread is using the system locale. You can get this (on Linux) by running:

$ locale

You should be able to use the other built-ins like locale_create/3 and locale_set/1, for example:

?- locale_create(Locale, "C", []),
   set_locale(Locale),
   findall(C, char_type(C, digit), Cs),
   locale_destroy(Locale).
Locale = <locale>(0x2043ec0),
Cs = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'].

I don't have any interesting locale installed on my system so I cannot easily check if this is really the problem.