Live data from Hacker News

I'm not mutable, I'm partially instantiated

blog.dnmfarrell.com

21–30 of 77 posts

Re: I'm not mutable, I'm partially instantiated

#21
post #4

I don't get where the `-` comes from in `key-value` result lines after the "refactoring" title. I feel like it should stay a `,` like at the beginning. Can someone more knowledgeable in Prolog explain that? Is that because of an hidden use of this `to_list` predicate that comes later in the post?

It's purely a convention to use terms of the form "key - value" for 2-tuples here (or '-'(key, value) in funtional/canonical notation which can be used as well). minus is just used because it's already predeclared as an infix operator, and indeed ','(key, value) could be used as well but comma is also used as argument separator and for conjunctions in clause bodies and thus tends to be avoided. You also can see '=' being used for the same thing eg.

    [ key = value, ...]
(for example, as used for representing attributes by SGML/XML parsing libs for SWI, Quintus/SICStus, and others), not to be confused with '=' being interpreted as unification operation in goals/clause bodies.

If you think about it, the simplest convention in Prolog to represent "assignment" of a value to a symbol (not a variable) would be

    key(value).
That is, to use the "key" atom as functor itself, rather than use functors/operators in ad-hoc ways. This is exactly what Quantum Prolog can do (optionally, and in addition to ISO Prolog's conventions).

Specifically, if you have a list of fact-like terms

    L = [ p(1), q(2), r(what(ever)) ]
then Quantum Prolog can answer queries against such term list, just like answering against the global default database eg.

    call(L ?- q(X))
binds

    X = 2
and would also bind additional values for q(X) on backtracking if the term list contained any. This is a natural extension to regular querying in Prolog because a term list [a, b] in Prolog's square bracket notation is just syntactic sugar for using the dot operator

    '.'(a, '.'(b, []))
and a Prolog program is syntactically just a list of clause terms.

In the container planning demo on the Quantum Prolog site [1], this feature is used for backtracking over (un)loading and travelling actions which would normally change state via destructive assert and retract calls and hence not allow backtracking to search for optimal sequences of actions.

[1]: https://quantumprolog.sgml.net/container-planning-demo/part2...

Re: I'm not mutable, I'm partially instantiated

#22
post #18

I am actually working on a logical query language that's a successor to prolog here: https://memelang.net/02/ . Any feedback appreciated!

It might be worth using standard vocabulary. For example:

> Reciprocal relations are their own inverse.

The usual word for this is "symmetric".

> Recursive relations can be chained to themselves infinitely. For example, "my ancestor's ancestor is also my ancestor."

The usual word for this is "transitive".

A reflexive, symmetric, transitive relation is called an "equivalence relation", and it can be used much like equality. It'd be nice if your language had support for this, though I don't immediately see how to add it.

Re: I'm not mutable, I'm partially instantiated

#24
Partial instantiation is cool and all, but tbh I prefer just capturing the initial incomplete attributes in one complete record, pass that around, and then instantiate the real thing when you have all attributes

    data class IncompletePerson(val name: String)

    data class Person(
      val name: String, 
      val email: String
    )
or

    data class Person(
      val initialAttributes: IncompletePerson, 
      val email: String
    )
if you want to nest it.

if you're the type to instead do this

    data class Person(
      val name: String, 
      val email: String?
    )
I never want to work with your code. Now, there's no disambiguation between the complete object and the incomplete one, I always have to check before doing anything with it, and people will inevitably try send an incomplete object someplace that can't handle it and generate bugs.

Re: I'm not mutable, I'm partially instantiated

#25
post #4

I don't get where the `-` comes from in `key-value` result lines after the "refactoring" title. I feel like it should stay a `,` like at the beginning. Can someone more knowledgeable in Prolog explain that? Is that because of an hidden use of this `to_list` predicate that comes later in the post?

It's purely a convention to use terms of the form "key - value" for 2-tuples here (or '-'(key, value) in funtional/canonical notation which can be used as well). minus is just used because it's already predeclared as an infix operator, and indeed ','(key, value) could be used as well but comma is also used as argument separator and for conjunctions in clause bodies and thus tends to be avoided. You also can see '=' b…

There's no -/2 operator in the initial definition of lookup/3 though:

  lookup(Key, dict(Key,X,Left,Right), Value) :-
      !
      ,X=Value.
  lookup(Key, dict(Keyl,X,Left,Right), Value) :-
      Key  Keyl
      ,lookup(Key,Right,Value).
You can also see that in the first call to lookup/3 where there's no -/2.

If I understand correctly, that's what the OP is asking: Where did the -/2 come from, not what it's for.

The call with the -/2 is under the heading "Refactoring the dictionary" so it's possible the author mixed up the implementations while writing the article and listed the output of an implementation that represents key-value pairs as -/2 terms.

The refactored version makes more sense btw and indeed I see the author switches to K-V later on in the article.

Re: I'm not mutable, I'm partially instantiated

#26

I've never used it in production, but I have a deep love of Prolog, just because of how different it is from any other programming language I've used. As a programming paradigm, it found it as eye-opening as functional programming. What I found interesting is that you are operating on logical statements and pattern matching, which often means that the same "function" can be used for multiple different things. For exa…

It doesn't scale that well because integers are their own, opaque thing in Prolog, and the is predicate is unidirectional. However, there's no inherent reason this has to be the case: you can construct your own representation of the integers from the Peano axioms, and recover bidirectionality of addition. (You'll want to be using some typed variant of Prolog with the "unary tree of units" optimisation, otherwise inte…

Check out the CLP(ℤ) library by Markus Triska, who is also the author of Scryer Prolog. It defines new comparison predicates that lets you use bidirectional logical programming on standard integers with standard math operations.

https://github.com/triska/clpz

Re: I'm not mutable, I'm partially instantiated

#27
post #16

Partially instantiated data structures are also available in Haskell (via Laziness), in OCaml (via tail modulo cons, https://inria.hal.science/hal-03146495/document ) and Koka (via constructor contexts, https://dl.acm.org/doi/pdf/10.1145/3656398 )

I don't think Haskell can do this, can have a growable linked list for example. 'last a' is 'last a', regardless what is between them (modulo shadowing and such).

And I suspect that Prolog's Partial Instantiation is, while not mutating data, but it is mutating references somewhere

Re: I'm not mutable, I'm partially instantiated

#28

I've never used it in production, but I have a deep love of Prolog, just because of how different it is from any other programming language I've used. As a programming paradigm, it found it as eye-opening as functional programming. What I found interesting is that you are operating on logical statements and pattern matching, which often means that the same "function" can be used for multiple different things. For exa…

It doesn't scale that well because integers are their own, opaque thing in Prolog, and the is predicate is unidirectional. However, there's no inherent reason this has to be the case: you can construct your own representation of the integers from the Peano axioms, and recover bidirectionality of addition. (You'll want to be using some typed variant of Prolog with the "unary tree of units" optimisation, otherwise inte…

“you can construct your own representation of the integers from the Peano axioms”

This is how the Idris prelude defines nat, the type of natural numbers (with some magic making it actually fast). I think that’s very cool.

Re: I'm not mutable, I'm partially instantiated

#29

I've never used it in production, but I have a deep love of Prolog, just because of how different it is from any other programming language I've used. As a programming paradigm, it found it as eye-opening as functional programming. What I found interesting is that you are operating on logical statements and pattern matching, which often means that the same "function" can be used for multiple different things. For exa…

It doesn't scale that well because integers are their own, opaque thing in Prolog, and the is predicate is unidirectional. However, there's no inherent reason this has to be the case: you can construct your own representation of the integers from the Peano axioms, and recover bidirectionality of addition. (You'll want to be using some typed variant of Prolog with the "unary tree of units" optimisation, otherwise inte…

There are many ways to recover relational behaviour. Libs such as clp(fd) (superseded by clp(Z)), clp(BNR) and others.

Re: I'm not mutable, I'm partially instantiated

#30
post #29

Earlier quoted context omitted.

It doesn't scale that well because integers are their own, opaque thing in Prolog, and the is predicate is unidirectional. However, there's no inherent reason this has to be the case: you can construct your own representation of the integers from the Peano axioms, and recover bidirectionality of addition. (You'll want to be using some typed variant of Prolog with the "unary tree of units" optimisation, otherwise inte…

There are many ways to recover relational behaviour. Libs such as clp(fd) (superseded by clp(Z)), clp(BNR) and others.

BNR notably works with real numbers and non linear constraints.
Post reply on HN