ichiban / prolog

The only reasonable scripting engine for Go.
MIT License
564 stars 27 forks source link

Add extension #314

Closed dylandprs closed 3 months ago

dylandprs commented 3 months ago

I have a Go program and a Prolog file, i use github.com/ichiban/prolog but missing features like atomic_list_concat. I saw there is an another librairy (github.com/guregu/predicates) but i dont understand how to add it. Can you explain how to add the extension, and specially, how to add the function atomic_list_concat ?

triska commented 3 months ago

Could you please post more about your specific need for atomic_list_concat/2? The use of this predicate usually indicates an opportunity for improvement in Prolog programs, by using better data structures such as lists of characters to represent text. By using lists of characters, you can use DCGs, phrase/2 and related predicates to reason about such data, and that makes many programs more efficient and also more general, because phrase/2 can be used in more modes than atomic_list_concat/2, and works also for partially instantiated terms.

dylandprs commented 3 months ago

My code is based on SWI-Prolog format and i have a predicate which transform a date and a time to a string like this :

change_datetime(Date, Hour, Res):- atomic_list_concat([Year, Month, Day], '-', Date), 
                                        atom_number(Year, YearNb), atom_number(Month, MonthNb), atom_number(Day, DayNb), 
                                        Res is YearNb * 100000000 + MonthNb * 1000000 + DayNb * 10000 + Hour.

?- change_datetime('2024-05-13', 1530, Res).
Res = 202405131530.
triska commented 3 months ago

If you need to "look into" atoms like that, then indeed lists of characters may be a better choice to represent your data. For instance, with this representation, the example can be readily solved with DCGs and standard predicates alone, for example as:

date_time_result(Date, Hour, Result) :-
        phrase((seq(Year),"-",seq(Month),"-",seq(Day)), Date),
        number_chars(YearNb, Year),
        number_chars(MonthNb, Month),
        number_chars(DayNb, Day),
        Result is YearNb*100_000_000 + MonthNb*1_000_000 + DayNb*10_000 + Hour.

Yielding:

?- date_time_result("2024-05-13", 1530, Result).
   Result = 202405131530
;  false.
dylandprs commented 3 months ago

Thank you for your response.

When i try your example, that seems not working. In Golang, when i print the result of the query, i only have a false (which means it doesn't find a result ?) . And when i try to execute the predicate in console, i have an error on phrase/2 :

ERROR: Type error: `list' expected, found `"2024-05-14"' (a string)

I have some restrictions on the entry of the predicate to change the datetime format, and it must match change_datetime('2024-05-13', 1530, Res). (date is an atom and not a string)

dylandprs commented 3 months ago

I found a solution to my problem, it's not the best solution but it works :

date_chars([Y1,Y2,Y3,Y4,'-',M1,M2,'-',D1,D2], Year, Month, Day) :-
    number_chars(Year, [Y1,Y2,Y3,Y4]),
    number_chars(Month, [M1,M2]),
    number_chars(Day, [D1,D2]).

change_datetime(Date, Hour, Result) :-
    atom_chars(Date, Chars),
    date_chars(Chars, Year, Month, Day),
    Result is Year*100000000 + Month*1000000 + Day*10000 + Hour.

Thank you for your help !

triska commented 3 months ago

One great advantage of your solution is that it now uses exclusively standard predicates and therefore works in all Prolog systems! Well done!

triska commented 3 months ago

Note also that there is no need to quote the atom -.