Picat Functions vs. Predicates 5 — Questions and Answers
Question 1: In Picat, `map(F, List) = [F(X) : X in List]` defines a higher-order map. Why must `F` be a function reference rather than a predicate reference here?
- Predicates cannot be passed as arguments
- The list comprehension builds its output from return values, requiring `F` to return a value (Correct answer)
- Picat prohibits higher-order predicates entirely
- List elements must be integers
Correct answer: The list comprehension builds its output from return values, requiring `F` to return a value
Each element `F(X)` must evaluate to a value for inclusion in the new list, so `F` must be a function.
Question 2: What distinguishes a Picat action rule (using `=>` with an event trigger) from a regular predicate clause?
- Action rules use `?=>` instead of `=>`
- Action rules are triggered by domain events during constraint solving, not by direct calls (Correct answer)
- Action rules are functions that return event objects
- Action rules require a `main` predicate to invoke them
Correct answer: Action rules are triggered by domain events during constraint solving, not by direct calls
Action rules fire automatically when a variable's domain changes during constraint propagation, unlike regular predicate clauses.
Question 3: Picat's tabling mechanism can be applied to predicates. What is the effect of `table` on a predicate `path/2`?
- It converts `path/2` into a function
- It memoizes computed results to avoid redundant recomputation during search (Correct answer)
- It forces `path/2` to always deterministically succeed
- It exports `path/2` to other modules automatically
Correct answer: It memoizes computed results to avoid redundant recomputation during search
The `table` declaration memoizes solutions, enabling efficient dynamic programming over predicates.
Question 4: In Picat, which syntax is used to define a function with multiple return clauses including a default case?
- Use `if-then-else` inside a single `=>` clause
- Write multiple `= Expr` clauses with pattern matching or guards, ending with a catch-all (Correct answer)
- Use `switch` with `case` labels
- Picat only allows one clause per function
Correct answer: Write multiple `= Expr` clauses with pattern matching or guards, ending with a catch-all
Multiple function clauses with patterns or guards are the idiomatic way to handle multiple cases.
Question 5: Given predicate `between(Lo, Hi, X)` that nondeterministically binds X to each integer in [Lo, Hi], how would you collect all solutions into a list?
- `L = between(1, 5, _)`
- `findall(X, between(1, 5, X), L)` (Correct answer)
- `L = [between(1,5,X) : X in 1..5]`
- `once(between(1,5,X), L=X)`
Correct answer: `findall(X, between(1, 5, X), L)`
`findall/3` collects all solutions of a goal into a list, bridging nondeterministic predicates and list data.
Question 6: Why is it generally preferred to implement a pure computation (e.g., converting Celsius to Fahrenheit) as a Picat function rather than a predicate?
- Functions execute faster due to JIT compilation
- A function returns the result directly, making call sites cleaner and enabling expression composition (Correct answer)
- Predicates cannot perform arithmetic in Picat
- Functions are checked for type safety at compile time
Correct answer: A function returns the result directly, making call sites cleaner and enabling expression composition
Pure computations benefit from function syntax because the result can be embedded in expressions without an extra output argument.
Question 7: What does it mean when Picat documentation says a predicate is `det` (deterministic)?
- The predicate always succeeds exactly once without leaving a choice point (Correct answer)
- The predicate runs in constant time
- The predicate is defined using `=` instead of `=>`
- The predicate uses tail recursion
Correct answer: The predicate always succeeds exactly once without leaving a choice point
A `det` predicate succeeds exactly once and leaves no choice points, behaving predictably like a function call.
In Picat, `map(F, List) = [F(X) : X in List]` defines a higher-order map.
Why must `F` be a function reference rather than a predicate reference here?