1,418 karma · joined December 17, 2022
The only thing I don't see is setup for local/in-house LLMs, but it's easy enough to spoof OpenAI calls if necessary.
Damn, I knew we were lazy but describing prompting as labor-intensive is impressively lazy even to me.
Obviously reading the rest of the abstract was too labor intensive for me but I'm hoping I can just hook a probe up to my drool and it can infer my desires from that.
God speed.
> "why would I want to translate my email into Polish?"
You rock!
> call_direct_and_indirect(IndirectCallTarget, Input, Result) :- call_direct(Input, Intermediate), % first-class call call(IndirectCallTarget, Intermediate, Result). % second-class call
I see we are at an unfortunate impasse. I assert what you are calling a "second-class call" is usually considered "first-class". I will leave the definition here for readers to decide for themselves. I rest my case and wish you a good day.
https://en.wikipedia.org/wiki/First-class_function
> Higher-order functions: passing functions as arguments
Further information: Higher-order function
In languages where functions are first-class citizens, functions can be passed
as arguments to other functions in the same way as other values (a function
taking another function as argument is called a higher-order function). In the
language Haskell:
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = f x : map f xsHowever, this is a charitable interpretation that is open to abuse if desired.
It is starting to sound like the criticism is that Prolog is not an object oriented programming language and does not pass contextual object information along with symbols in the same way SICP-style higher order functions are treated in functional programming languages.
This is by design, Prolog is a logic language that describes relationships, not a procedural language.
There is no behavioral difference that distinguishes a Prolog predicate as not "first class". There are many metapredicates designed to accept predicates as arguments, such as maplist/N. This is the primary criteria for supporting first class "callables" (another word poorly suited for Prolog, but I'm admitting it for purposes of conversation) in other languages. I would have assumed that would be a sufficient behavioral affordance.
> there are first-class callable things and second-class callable things
To make this more concrete, please provide some examples of "first-class" and "second-class" "callable things" in Prolog, as well as an example of "first class" and "second class" "callable things" in another language.
Given your level of confidence in your argument, I assume this should be fairly easy to do. Then we might have a concrete basis for discussion.
"First class" meaning, can be the arguments to a predicate or processed as data.
Predicates (and only predicates) can be called with `call/N` -- although you could write a meta-interpreter with different properties. You could pass in the number `1` and call a randomly determined predicate, as an absurd example.
Perhaps you mean, "the head and body of a predicate are not first class" ? This again is false. They are valid data and can be processed as such -- please see [4] for clarification.
Perhaps you mean "they cannot be looked up dynamically at runtime" -- this is also false, please see [3].
Are there other eligibility requirements for "first class" that we should discuss?
Otherwise, many syntax and semantics are similar.
No dependency on Datomic as Datomic is Java and DataScript is JavaScript.
Certainly.
> For [1], you would either need to pass the AVL tree around or to have it as a global (which is not wanted), and instead pass the key (the "this" context which is different for different mazes) for the context around.
Not sure how tracking references is different here than any other programming language. Passing objects around is pretty common in OO programming. An AVL tree is just the underlying abstraction used to implement the object. You don't have to implicitly supply the "this" parameter to each "object" predicate if you don't want to -- you could insert that yourself via compilation (with term/goal expansion)[4] or interpretation (via meta-interpreters) if you were really interested in that level of syntactic sugar.
> For [2] again you have a global table (with copying semantics as for assert/retract? or maybe without copying? the docs don't say). But again you would need to pass a key around.
You could use global or local semantics as desirable. The blackboard has a global version that is persistent across application state or a local version that provides lexical context which unwinds on backtracking. Not sure how "passing a key around" is different than most other forms of programming, but if you wanted to compile it away, please review the techniques listed above.
> [3] is... yeah. I mean, sure, you could demonstrate this with a toy metainterpreter on a toy example. But do you really want to run your whole application inside a metainterpreter?
A "toy" meta-interpreter? Meta-interpreters are as fundamental to Prolog as for-loops are to Python. Certain applications, such as games, are run "entirely inside a loop", so I'm not sure how this criticism applies. You can run as much or as little of your application inside a meta-interpreter as you want. The value proposition of Prolog is that the simple homoiconic syntax allows for powerful meta-interpretation. I'd suggest checking out the video I linked to in [3] if you have doubts on that topic.
> One could also abuse DCG syntax, with the context being some state object instead of a DCG list.
State transitions (a sequence of states) are a great use for DCG syntax! I wouldn't call that "abuse".
> A more practical way would be Logtalk-like code generation. The most practical way would be actual Logtalk.
If you are willing to give up the most powerful features of Prolog, sure.
> Unfortunately, last I heard Scryer refused to host Logtalk for no real reason.
Hmm, I wonder if that's the real story :)
[4]: Please see Section 3 of my talk if you are interested in a more thorough explanation of goal/term expansion. https://docs.google.com/presentation/d/e/2PACX-1vR4Q0Ohs66mj...
> Prolog predicates are not first class values.
Predicates are trivially called, even as variables, with the `call/N` metapredicate.
> Mapping and filtering is awkward
In what sense? The declarative semantics...?
> Arithmetic is awkward
In what sense...? Have you seen clpz?
> The CLP examples aren't integrated with Prolog's Horn clause resolution model
In what sense...? clpz and clpb do this magnificently.
> Indexing and search strategies are not under programmer control.
Most ship with SLG resolution or you can write your own resolution strategy with a simple metainterpreter as an intermediate exercise -- but SLD resolution is already pretty good. In general not needing to think about the indexing and search strategies are a highlight of the declarative semantics of Prolog, its odd to see someone with a "long standing love affair with Prolog" list this as a drawback.
> Modes are awkward.
Modal programming is a defining feature of Prolog. Tell me more about this "long standing love affair", again?
> I've been an enthusiastic Prolog programmer since the mid 1980s
If you are still struggling with mapping, filtering, arithmetic, `call/N`, and CLP in Prolog after nearly 45 years of "enthusiastic" programming, I'd highly recommend checking out Triska's Power of Prolog videos for some guidance, I think you will find them very illuminating.
It is not Datalog syntax but heavily inspired by Datalog.
I'm throwing this in here just for clarification, I don't want to see Datomic as collateral damage in this conversation.
However quite frankly the most powerful way to do this is not obvious because it doesn't translate well to other languages: meta-interpreters[3].
[1]: https://www.scryer.pl/assoc
[1]: https://dcnorris.github.io/precautionary/index.html
[2]: https://github.com/mthom/scryer-prolog/discussions/2441
[3]: https://link.springer.com/chapter/10.1007/978-981-97-2300-3_...
Regarding how, check out Power of Prolog on YouTube.
Also not sure what you mean, CLP is a first class consideration in many Prologs, esp Scryer Prolog. Check these crazy demos out:
[1] https://youtu.be/h5Xy4YjCZxM
[2] https://youtu.be/5KUdEZTu06o
Just look at this Sudoku solver code (see [2] for explanation):
sudoku(Rows) :-
length(Rows, 9),
maplist(same_length(Rows), Rows),
append(Rows, Vs), Vs ins 1..9,
maplist(all_distinct, Rows),
transpose(Rows, Columns),
maplist(all_distinct, Columns),
Rows = [As,Bs,Cs,Ds,Es,Fs,Gs,Hs,Is],
blocks(As, Bs, Cs),
blocks(Ds, Es, Fs),
blocks(Gs, Hs, Is).
blocks([], [], []).
blocks([N1,N2,N3|Ns1], [N4,N5,N6|Ns2], [N7,N8,N9|Ns3]) :-
all_distinct([N1,N2,N3,N4,N5,N6,N7,N8,N9]),
blocks(Ns1, Ns2, Ns3).
I have yet to see more elegant code in a general purpose language.[3]: https://github.com/mthom/scryer-prolog/discussions/2347#disc...
You would ask reasonable questions like, "for God's sake, why?". It feels like you wouldn't use Prolog for anything besides an intellectual game.
Regarding the why:
Some of those reasons include Definite Clause Grammars, Meta-Interpreters, 1st class constraint logic programming, reified conditionals, and term/goal expansion.
There are a lot of exciting modern advances with Prolog, especially Scryer Prolog.
Check out Power of Prolog and get your mind blown: https://youtube.com/@thepowerofprolog
Of course I since realized that was the tip of the iceberg.
https://www.seattletimes.com/entertainment/pagliacci-classic...