trealla-prolog / go

Trealla Prolog embedded in Go using WASM
MIT License
79 stars 3 forks source link

a list of a single char is returned with double quotes #15

Open jhwu68 opened 1 week ago

jhwu68 commented 1 week ago

@guregu Hi, we're running into this weird behavior, it's probably a trealla thing, since it doesn't happen with swi-prolog. Is there a quick fix or workaround?

Screenshot 2024-10-29 at 17 13 11
guregu commented 1 week ago

Hello @jhwu68, depends on where you're running into this. By default [a] and "a" are just two ways of writing the same thing, so it's (supposed to be) harmless.

?- "a" = [a].
   true.
?- "ab" = [a, b].
   true.

You can disable this in the terminal output with set_prolog_flag(answer_write_options, [double_quotes(false)]).

?- set_prolog_flag(answer_write_options, [double_quotes(false)]).
   true.
?- findall(Col, member(Col, [a]), List).                                                                                                                                                
   List = [a].

If you want to run this automatically when you load a script you can add this to the file:

:- initialization(set_prolog_flag(answer_write_options, [double_quotes(false)])).

and it should apply globally.

But, if you're running into an issue, say with Scan or some other encoding/decoding thing, maybe there's another issue. Let me know and I'll help out.

BTW the reason SWI gives you a different result is that by default SWI treats double-quoted strings as lists of character codes instead of lists of single characters. You can configure Trealla to do this too but it breaks a lot of stuff. In general the character way (Trealla default) is "better".

jhwu68 commented 1 week ago

@guregu thanks for the explanation. I kind of understand they represent the same thing. but it's not parsed into slice in go, where we check the type of the value.

i tried wth adding initialization, but still the same result

Screenshot 2024-10-30 at 18 04 39

and the specific issue we have is

Screenshot 2024-10-30 at 17 55 07

i made a workaround in go https://github.com/aukai/stream.api/pull/1296

guregu commented 1 week ago

@jhwu68 They removed me from that repo recently ;( Are you using .Scan? I think I found the issue, maybe! Pushing now

guregu commented 1 week ago

Oh, I can probably guess what it is assuming that code hasn't changed much. I see... sorry about that. My fix kinda helps but not for your case (yet). I imagine your workaround is something like

var cols []trealla.Term
switch x := cmp.Args[4].(type) {
case []trealla.Term:
    cols = x
case string:
    for char := range x {
        cols = append(cols, String(char))
    }
}

which should be fine but it's not too pretty to look at. I'll add a nicer way to do this so you can just write trealla.Convert(cmp.Args[4], &cols) or something.

guregu commented 1 week ago

For this use case it might be nicest to disable strings in results in general. I should be able to add a query option that does that. I’ll get back to you.

jhwu68 commented 1 week ago

They removed me from that repo recently ;(

😢 yeah, the workaround is similar to that. Thanks for looking into it!

guregu commented 5 days ago

@jhwu68 I improved the Scan function in the latest release, so you can unmarshal query results into structs:

type pair struct {
    trealla.Functor `prolog:"-/2"`
    Key     trealla.Term
    Value   trealla.Term
}
type fieldDef struct {
    trealla.Functor `prolog:"field/5"`
    Path    Atom
    Type    trealla.Term
    Options []trealla.Term
    Rules   []pair
    Cols    []trealla.Atom
}
var result struct {
    Fields []fieldDef
}
answer, err := pl.QueryOnce(`findall(..., Fields).`)
answer.Solution.Scan(&result)

It will be smart enough to handle turning strings into slices, and less .(type) shenanigans too. I added some test cases with the string -> slice thing so hopefully you won't run into the same problem again.