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

[Query] Signal structured error (NoAnswer) instead of just Error #384

Merged
merged 1 commit into from
Nov 12, 2024

Conversation

shingarov
Copy link
Owner

No description provided.

@shingarov shingarov requested a review from janvrany November 12, 2024 09:06
@janvrany
Copy link
Collaborator

I like the idea but before I merge it, I'd like to know how where this is going to be used. The thing is, there's no NoAnswer in Smalltalk/X and the Query implementation is different. I'm not opposed changing St/X but that needs a bit of work.
I'm on it already.

@janvrany
Copy link
Collaborator

Okay, adding NoAnswer to St/X seems to be quite tricky, there the default answer is nil and a lot of code depends on it (there's 38 subclasses of Query in "base image"). More thinking is needed.

@shingarov
Copy link
Owner Author

the default answer is nil and a lot of code depends on it. More thinking is needed.

After a few more hours of contemplating, I think I am starting to understand this a bit better. We are looking at another example of consequences of dynamic typing — a fundamental design choice in Smalltalk — on compositionality.

Consider the following example of the original question, due to Kleisli, seemingly unrelated to computer programming: the equation

ax = b

can be solved for x as b/a. What if a=0? We can special-case it (NB: this is happening in the control plane) and say "unless a=0"; but what if ax=b is part of a larger investigation, so a and b come from some other calculations, and x is used some later calculation? The permutations of special-cases can quickly become unmanageable. Another approach is to special-case in the data plane and adjoin NaN to the numbers (the possible values of x). So we are looking at a functor lifting numbers to maybe-numbers; and they compose because trying to operate on NaN gives you another NaN, etc. This is just Maybe with a special name ("NaN" instead of "nil").

In Haskell, many functions "F" come in two variants, "F" and "maybeF". In Smalltalk terms, "divide" would signal a ZeroDivide but "maybeDivide" would answer NaN. Or, Array>>at: would signal SubscriptOutOfBounds but Array>>maybeAt: would answer nil. This composes in the data plane, and while in Haskell it has to be explicitly plumbed through the Kleisli arrow, in Smalltalk the array member could itself be nil (e.g. if it came from a failed computation).

So for our Query, this resolves nicely the problem of "what happens if the answer does exist and is actually nil?" The question that remains, is naming consistency, but we have that problem across the board. It is in general difficult to say by just looking at a selector, whether a failure will be signaled in the control or in the data plane. In MA I have been trying to use maybeF-style names, especially when transliterating from LH, but it's not exactly parallel because in Smalltalk the Maybe is implicit (anything can be nil).

I'd like to know how where this is going to be used.

At this point in time, there are no uses of Query in the MA codebase; everything still uses the old #runReader:initialState:. This is going to change in the future but I would like to do more foundational work in this area, I want to have the Reader concept (which is — most stunningly!!! — just the left adjoint of function application, #value:) decoupled from what to key it off (Class or Symbol). So perhaps we can pospone the change in #defaultResumeValue, and limit this PR to just introducing the class NoAnswer. My use of it is in 3c20629 (I meant to merge that later after we have concensus whether we like the NoAnswer exception at all, which we seem like it).

@shingarov
Copy link
Owner Author

shingarov commented Nov 12, 2024

adding NoAnswer to St/X seems to be quite tricky, there the default answer is nil and a lot of code depends on it (there's 38 subclasses of Query in "base image")

Oh, wait! Can you explain this again? How does changing #error: to NoAnswer signal affect anything about the default answer? We are just swapping one error class for another (which happens to be the first one's subclass), no??

@shingarov
Copy link
Owner Author

Something like 539dffa for now?

@janvrany janvrany merged commit bb7cb0e into pure-z3 Nov 12, 2024
9 checks passed
@shingarov shingarov deleted the structured-noanswer branch November 12, 2024 22:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants