Re: [SWIPL] Re: pedagogy

[Cc’ed to new forum]

write_canonical does help with operators, but yes, it’d be useful if there was a form that expanded a list.

If interop is a problem, maybe add write_very_canonical that does ‘[|]’

You can write lists in the standard canonical representation using

1 ?- write_term([a,b,c], [dotlists(true)]).
.(a,.(b,.(c,[])))

This is a very poor format. Not only does it exhibit something that
should IMO have remained hidden, but reading this is really expensive
as you only know that the .(a, …) reduces to a ./2 cell and not a
./3 or more cell at the very end. This implies you have to carry
around a lot of information while parsing such lists. Compare that
with [a,b,c] where you can reduce after every comma.

Now working with XSB which arrived rather late on the ISO
standardization. They apparently never bothered with this and
simply write [a,b,c] for a list using write_canonical/1.

Cheers --- Jan
1 Like

Since the original subject was “pedagogy” and I know nothing about that, I feel obliged to comment.

There is nothing pedagogical in trying too aggressively to pre-chew things for “beginners”. Anything that is not an instinct is something that we (human animals) must learn, either by doing, by listening to a lecture, or by reading textbooks. This is my first comment.

The second comment is about lists. A list is an abstract data type. Something like L = [H|T] is an operation on a list that decomposes it in a head and a tail (or first element and rest of the list). It might be useful in some cases to know how it is implemented, but must we know that in order to use it? I am not sure. Must we explain (or show) how nth1/3 is implemented in order to tell the “user” that it is not a constant time operation on lists? And if there is never reason to write code that uses the list functor (./2 or '[|]'/2 or whatever), do we need to really know about it?

So many question marks :wink:

Given that lists have precisely one relation defined, [|], it’s easy for a beginner so informed to infer that nth0 is not fast.

The way I understand it, the issue is how useful it is to know how a list is implemented.

5 or 6 years ago (“beginner”) I realized that this knowledge was obligatory to understanding why people are reacting in a certain way when asked stupid questions about Prolog lists. Now (still beginner but knowing programmers marginally better) I fully appreciate the importance of that knowledge.

But in practice, getting stuck in this mindset has negative consequences, as Jan above already explained (if I read a bit between the lines, sorry if I misinterpreted his comments!)

Which is why I’d actually recommend that you just do the little hack I showed above and print terms, even lists, in their “canonical” representation, then explain how you did the hack, why it is a hack, why it can’t handle lists with a length of 100 or more, how one could make it handle lists of length of 100 or more, why abstract data types are a good thing, and so on. Ah, the possibilities :wink:

If you want to know how terms are represented you may consider the package gvterm:

?- use_module(library(gvterm)).
?- dotty_term([a,b,c]).

gvterm

Not very portable (uses Python and xdot). Should add it to SWISH as the core of the library converts a Prolog term into a Graphviz dot representation anyway. Written to debug variant/2 :slight_smile:

P.s. I do agree that knowing the real representation matters. Perhaps we can change good old display/1 to take that role again?

2 Likes

I guess that’s exactly what Anne originally had in mind. Between all the things available at the moment, I could not come up with a clean way to achieve what she seemed to need.

1 Like

Pushed 5f680b1be8f153db188dc37fc809135b087e9a65 to make display/1,2 behave this way:

101 ?- display([a, {b}]).
'[|]'(a,'[|]'({}(b),[]))
2 Likes

Mostly I needed this for teaching beginning prolog - beginners need a way to see how their prolog parses without the syntactic sugar confusing them.

to infer that nth0 is not fast

I would not say that! Well, assuming the hard work behind, like the JIT indexing and the already efficient Prolog library…

This is great! Glad to see it.
display/1 is just what’s needed -some zero config, zero syntactic sugar representation.

Last time I gave a full ‘learn prolog’ workshop was in Dec. at Functional Conf. I used ‘implement complex arithmetic’ as a problem. Students struggled with the operators.

This is an old and complex debate, and will always side new users against veterans. Should we have syntactic sugar that makes the language read more naturally, or eschew it and have syntactic transparency.
If one still has a good grasp of the language, then one has syntactic transparency even in the face of sugar, and it becomes an aid. If one is struggling to learn, then it can be a source of confusion.
Giving the student a simple way to answer the ‘what does this represent’ question for themselves has pedagogic value as student centered learning.