Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🧠 Logic: ⛓️ foldl/4 predicate #788

Open
3 tasks
ccamel opened this issue Oct 15, 2024 · 5 comments
Open
3 tasks

🧠 Logic: ⛓️ foldl/4 predicate #788

ccamel opened this issue Oct 15, 2024 · 5 comments

Comments

@ccamel
Copy link
Member

ccamel commented Oct 15, 2024

📝 Purpose

Implement the foldl/4 Prolog predicate. This predicate performs a fold (left-fold) over a list, applying a goal to each element in the list, starting with an initial accumulator value and producing a final value after all elements are processed.

Rationale

This predicate is quite common and can facilitate the expression of certain governance rules, especially in scenarios where an aggregate decision or value must be derived from a list of inputs by applying a consistent operation across them...

🧪 Expected behavior

foldl/4 folds a list head-to-tail (“fold-left”), applying each element to the specified Goal. V0 serves as the initial accumulator value, and V is the final result of the folding operation.

foldl(:Goal, +List, +V0, -V)

Where:

  • Goal: A predicate that is applied to the elements of List and the accumulator. It should accept three arguments: an element of List, the current accumulator, and the new accumulator.
  • List: A list of elements to be folded over.
  • V0: The initial accumulator value.
  • V: The final value of the accumulator after folding the entire list.

🎯 Example

?- foldl(plus, [1, 2, 3, 4], 0, Result).
Result = 10.

?- foldl(atomic_list_concat, ['hello', ' ', 'world'], '', Result).
Result = 'hello world'.

✅ Acceptance Criteria

  • The predicate is implemented according to the described behavior and examples
  • The predicate passes all test cases
  • Documentation is updated accordingly.

🔗 References and linked predicate

@amimart
Copy link
Member

amimart commented Oct 16, 2024

That's an important I agree.

I also think it is easier to implement it in Prolog directly than as a custom Go predicate:

foldl(Goal, [H|T], Result) :-
    foldl(Goal, T, H, Result).
foldl(Goal, [H|T], Acc, Result) :-
    call(Goal, Acc, H, NewAcc),
    foldl(Goal, T, NewAcc, Result).
foldl(_Goal, [], Result, Result).

I'd like to propose to allow implementing new predicates directly in prolog, which would be added to the bootstrap.pl when loading the VM.

I recall for example that we've implemented the source_files/1 predicate this way, but I'm not comfortable editing the bootstrapping program directly as we don't benefit from autogenerated documentation, tests, etc.. I'd like instead to propose an alternative way of registering predicates by providing its related Prolog code the registry would load after the bootstrap program.

What do you think @ccamel ? We may lose in performance though, maybe some benchmarks could help us on that

@ccamel
Copy link
Member Author

ccamel commented Oct 17, 2024

Hey! I agree. IMHO, native predicate implementations should be reserved for:

  • Predicates that need to interact with the environment/system.
  • Predicates where the Prolog implementation complexity makes a native approach preferable.

Regarding foldl/n, you're right, this is a typical predicate that can be implemented in pure Prolog. And that's exactly what swi-prolog does, afais: implemented it in apply.pl as follows:

foldl(Goal, List, V0, V) :-
    foldl_(List, Goal, V0, V).

foldl_([], _, V, V).
foldl_([H|T], Goal, V0, V) :-
    call(Goal, H, V0, V1),
    foldl_(T, Goal, V1, V).

Further considerations.

  1. Prolog source organization:
  • The bootstrap should serve only as a minimalist foundation for VM execution (for now)
  • Better approach: Split into modules, similar to existing Go files (1 file = one module, but we could consider to have 1 pkg = one module)
  • Each module would contain:
    • Native predicates in Go
    • Source predicates in Prolog
  • Like native predicates, source predicates will need to be compiled and executed in the VM

Note: bootstrap.pl will be deprecated once module implementation is available in ichiban/prolog (see PR ichiban/prolog#307), and we can leverage it to treat our modules as first-class Prolog citizens, enabling dynamic module loading at runtime and proper module scoping and visibility rules...

  1. Documentation:
  • The current documentation generator needs to be extended to extract predicate descriptions directly from prolog source files. This should be a relatively straightforward enhancement, I believe.
  1. Performance considerations:
  • As you mentioned, benchmarking would be great to have.
  • Potential optimization: Implement bytecode caching for compiled predicates.

If you want to move forward on these topics, we should create tickets to address the different steps. Also, some topics need to be addressed in axone-protocol/prolog.

@solthereum
Copy link

Hi, Christope, sorry for leaving comment here without your agreement and respecting the team rule. Because I wanna contribute to Axone team's development and join your team, so I am going to solve issues. So could you give me some issue to be solved quickly as test task?

@ccamel
Copy link
Member Author

ccamel commented Dec 5, 2024

@solthereum please contact us on our discord server.

@solthereum
Copy link

thanks @ccamel, I left message to you.
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: 📋 Backlog
Development

No branches or pull requests

3 participants