Is it possible to throw an exception in predicates?

Good day.
The question is about code purity and harmony of architecture. It is no secret that predicates are functions that must return a Boolean value, answering any question (is directory exists?). Since I started a year ago, tightly burned out exceptions (because they rule), now I rarely return false or null in cases where false or null must result in discontinuance of the program. I continue to return when the situation allowed, but when it's a mistake always throw an exception.

In fact, the crux of the matter is that in some cases, it is convenient to put the exception in the predicate. Thus, it is, in some cases, will only return true or throw an exception. It is better not to do, right? And how to do in such cases, if the code generasi exception, I want to encapsulate that into a function? Doing an additional function wrapper around the predicate?

Finish the question with an example.
<?php

class CheckForNewPhoto
{
 public function handle(Repositories\MosaicRepository $MosaicRepository)
{
 if($this->isDirectoryNameCorrect()) {
 // previously exception was thrown here, I think it's ugly
 // do stuff
}

 throw new Exceptions\UnexpectedError(
 'Something wrong here'
);
}

/**
 * This is the predicate. I did so to rid the entry point,
 * function handle from hell emission of exceptions when a checked a lot
 * conditions and thrown a lot of exceptions in a single method.
 * When one method is > a test > strictly related exceptions
 * it is beautiful.
*/
 private function isDirectoryNameCorrect()
{
 if(!config('mosaic.directory', null)) {
 throw new exception\InvalidSettingsException(
 'Directory for mosaic photos is not setup properly'
);
}

 return true;
}
}

Thanks in advance.
March 23rd 20 at 18:45
8 answers
March 23rd 20 at 18:47
Solution
Holding a hammer sees only nails


It's about you. The predicate must return true/false. Acceptany needed to catch mistakes and passed up the stack.

Life example: the question is, whether cakes or the seller says it turns and walks away
Funny example, like) Acceptany need in order to catch any program state, which is incorrect. For example, if passed (or forget to specify) invalid directory name - exception. Thus, no checks for null and false where they can be avoided. Another thing is that in the example I tried to replace false with the exception that really is not very good. - Stewart commented on March 23rd 20 at 18:50
@Stewart, I have simplified for quick understanding) - Willis6 commented on March 23rd 20 at 18:53
March 23rd 20 at 18:49
Solution
Predicates return a Boolean expression and a point. If it returns something else, then it is not a predicate.
Many methods like working with predicates, and they will not work correctly with a function that throws exceptions. So you might want to combine/merge several desired functions in your case, rather than trying to create one for all applications.
March 23rd 20 at 18:51
Solution
Here is an example:
void checkDirectory( const Dir& dir ) {
 if (isDirBad( dir ))
 throw "The directory is bad bad directory";
}

void File::open( const FileName& fn ) {
 try {
 checkDirectory( Dir( fn ));
openFile(fn);
}
 catch( const char* msg ) {
 std::cerr << msg << std::endl;
}
}

It is logical that the predicate `isDirBad()` should not throw an exception, because it will be oil-fired.
Let's just say - good design is that the exception generates the user's program, and the library is working with predicates. In this case, the library is easily ported for use in other programming languages.
March 23rd 20 at 18:53
Example just perfectly illustrates what exceptions there are and the gift is not necessary.

The question isDirectoryNameCorrect we want to get only "Yes" or "no".
While we are not worried about why no is the set of characters in the name invalid, then if the disk fell down, whether the rights is not enough - we are not interested.
March 23rd 20 at 18:55
The problem is when the exception to throw and when to catch! Specifically in your example you will have to catch the exception, terminate the operation of the file and continue execution.

Do you want to drop the application if the user has selected in settings the wrong directory? For example, we had selected the flash drive and then it is removed, your program will try to open the rolled and fall.
March 23rd 20 at 18:57
The exception is good name. Accurate. Successful.
They should be used in unintended health situations.

You described the situation - staff.
Here correctly return true or false.
March 23rd 20 at 18:59
The exception is a bad name. Confusing. Unsuccessful.
In fact, behind it is an alternative control flow: is the normal course of program execution, is there a way to teleport from point of excitation exception to the point of processing. And this is very convenient: for example, looking for something recursive traversal on the graph, found - threw the exception, and picked up his handler outside the function of the bypass. It is very convenient - no need when you exit the function to return true/false, and at the point of call to check it out, it turns out simply and elegantly.
with goto still kosher - alicia_Tremblay commented on March 23rd 20 at 19:02
@alicia_Tremblay, you don't understand, but I will explain to you all ) the Problem with goto was that it was allowed to jump inside any structure or cascade designs, Yes, Yes, exactly. No problem to jump out of something there- you can do a return anywhere in the function body, or break, from any place of the loop body.
Ponder on that ) - Tianna.Hessel commented on March 23rd 20 at 19:05
The microscope is a bad name, confusing. In fact, behind it is a heavy object that is supposed to crack nuts.

Using something not intended, you run the risk of windings in contradiction with the properties inherent to those who created it and tools. In the case of exceptions, you try to stop debugging, consume more memory and CPU time and make code less obvious. Because exceptions are designed for exception - laury.Schup commented on March 23rd 20 at 19:08
@laury.Schup, you must be very clever, but still something don't know. But do not worry - you have me, who will tell you. There is such a language, python, and exclusions in this surprisingly lightweight, fast, and, most importantly, are widely used where they are comfortable. An example of such a case I brought. - Tianna.Hessel commented on March 23rd 20 at 19:11
@Tianna.Hessel, thank you for you enlightened me, nice to meet a knowledgeable person. Only I have a few questions.

1. The example code specifies it seems to me that this is not Python and PHP
2. I would like to compare the exception and return value memory:

try: 
 b = 1/0
except Exception as e:
 pint(e.__traceback__)


Judging by this example is stored inside the exception still callstack the place in which it happened. Boolean in Python also stores callstack? Have you conducted experiments in order to verify your and approval and if we get acquainted with their results ?

I've found only here is there and here are the results:

100,000 iterations
with_try (168.793 ms)
with_try_exc (223.589 ms)
without_try (24.877 ms)
without_try_not (20.992 ms) - laury.Schup commented on March 23rd 20 at 19:14
@laury.Schup, here are a couple of recursive functions f and g, they nothing to do - just call 500 times. The difference in speed, 2/5 in favor of the ordinary. But they don't do anything at all.
from time import time


def timer(f):
 def wrapper(*args, **kwargs):
 t res = time(), f(*args, **kwargs)
 print("{:12s}, sec: {:f}".format(f.__name__, time() - t))
 return res

 return wrapper


def f(u):
 if u == 500:
 raise TabError()
 f(u + 1)


@timer
def ff(n):
 for _ in range(n):
try:
f(0)
 except TabError:
pass


def g(u):
 if u == 500:
return
 g(u + 1)


@timer
def gg(n):
 for _ in range(n):
g(0)


N = 1000
ff(N)
gg(N)

PS used TabError, because it is not a pity. - Tianna.Hessel commented on March 23rd 20 at 19:17
@Tianna.Hessel, that is, according to your measurements, acceptany themselves inhibit only 2.5 times?
As with the answers to the other questions?

from time import time


As I see it, finding new applications not intended for this things is your strong suit. Like python has a timeit, which is designed for benchmarking and will do everything for you and more precise - why you have not used it. Why these decorators?

(I'm not a python programmer, just googled python benchmarking) - laury.Schup commented on March 23rd 20 at 19:20
As I see it, finding new applications not intended for this things is your strong suit.

@laury.Schup, labels can your forehead pasted, since you are such a fan. The answer to the question of speed is exhausted. From memory all trivial - an exception handler frees the entire chain of stack frames until a marked frame, there is no parallel "callstack" is not needed.

that is, according to your measurements, acceptany themselves inhibit only 2.5 times?
Even a bit awkward for you - even code to run in a sandbox not worthy. - Tianna.Hessel commented on March 23rd 20 at 19:23
@Tianna.Hessel,
labels can your forehead pasted


Sorry, was emotional. Just use timer + decorator + cycle, where everything is already there, along with the repetition of several times a little amused.

The answer to the question of speed is exhausted.


OK OK. On the benchmark I get ~20+-5% (I just started a few times what you wrote, I broke to figure out how in the Python to do it normally).

Now we have the author of the question to recommend something, it PHP. How is it? You for himself cleverly?

From memory all trivial - an exception handler frees the entire chain of stack frames until a marked frame, there is no parallel "callstack" is not needed.


Link to TracBack is stored in the object-exception and it is better not to assign, as I understand it. And why is it stored there? Because exceptions are for exceptional situations and need a diagnosis.

Even as it is embarrassing for you


Well, I was corrected. - laury.Schup commented on March 23rd 20 at 19:26
Now we have the author of the question to recommend something, it PHP. How is it? You for himself cleverly?

@laury.Schup, I am completely at ease. The default set is very common task is to develop a good attitude towards the exceptions, and gave a practical example. I pointed to those aspects of the exceptions that were missed, and gave a counterexample. The remaining defendants made weaker: they were dogma )

See that tracecom: at the time of initiation of the exception stack we need to free up until the frame where the handler is. The stack would in any exempt single-shot output functions, but not - from falling into the clutches of the processor. If it was the handler by default- it would have printed this funeral drasbek and emergency completed the program. If the hands - well, something you've taken, but stack it would still be released.

Should appreciate the difference between Python and C++: a compiled language in non-standard stack unwinding is an expensive task if the stack was created by pointers and allocated memory, it should release. In Python the same thing, but there is a function call is an expensive task, so in this background, non-standard stack unwinding - no question. - Tianna.Hessel commented on March 23rd 20 at 19:29
@Tianna.Hessel,

The default set is very common task is to develop a good attitude towards the exceptions, and gave a practical example.


You gave a practical example And generalization (feature called incorrectly). Maybe on some specific language with a specific common problem this technique works. But, the feature is not meant for this. If someone made a cast iron microscope, which were in some situations it is convenient to crack nuts, it does not mean that 1. It is for this purpose intended 2. Everything in the world of microscopes is to use.

To use something not on purpose, but you have to think that all the others will rely on the main purpose.

If the hands - well, something you've taken, but stack it would still be released.


I gave a link to an article where it was said that if you remember the exception in the external variable, then the stack is released, and will be a circular reference.

In Python the same thing, but there is a function call is an expensive task


That is no exception, lightweight and all the rest heavy? - laury.Schup commented on March 23rd 20 at 19:32
@laury.Schup, enough with the metaphor of iron microscope. The whole premise of my answer concisely formulated in the second line: "In fact, behind it is an alternative control flow". I believe that awareness of this fact is much more useful trivial dispute ostrokonechniki and big-endian on predicates. To illustrate, I gave an example - otherwise, my assertion would be unfounded. Yes, it is a working example, I use such tricks in production code. And no, I donĂ­t want to impose.
Yes, the term "exception" - not the best. No, I was not involved in the selection more successful. Yes, the metaphor except perhaps useful when you enter this technology in the educational process. Yes, in the future, it obscures what I have said.
On release of the stack - I have a few strongly expressed. Stack in Python is not a stack in C++. The stack frame is a dictionary, so here. And release the stack frame does the garbage collector. So if you hang it external links - it may not be free. That's just why the heck to do - I'll never know ) - Tianna.Hessel commented on March 23rd 20 at 19:35
@Tianna.Hessel,
"In fact, behind it is an alternative control flow".


Behind this lies not only an alternative control flow, but the message, the ability to display the backtrace of the default behavior with the withdrawal of stacktrace, the ability to use debugging tools for SIGNALIZACII call exception, as well as brakes when you use (try it in your primmer to reduce the call depth of up to 2 you get the slow two times, it is necessary to consider, for example, if you have 99 percent of the calls shallow recursion, and there is a 1% deep)

Here's another metaphor - you bought a jar that says "salt" and put sugar. Unlike exceptions and microscope, tin tin is absolutely the same as with the word "sugar", it is, except the label, not designed for salt. But this misuse can be nuances.

That's just why the heck to do - mind I will not put


Someone read your answer and decided that it's the same as any other return value, only the flow control and the other decided, for example, to memorize the exceptions in the list, then to use. - laury.Schup commented on March 23rd 20 at 19:38
@laury.Schup, not bothered about the same?
I pointed to those aspects of the exceptions that were missed
and about everything else I can tell you, but not me - I in General in course.
If someone, having in mind not a tool for critical thinking and creative application, but something simpler, decide yourself something wrong - I sympathize, but not to tears. - Tianna.Hessel commented on March 23rd 20 at 19:41
@Tianna.Hessel, then what is the point in your statement here? Asking the question - beginner. The skilled person would have crawled into the documentation or used a search and found out. To use the critical thinking necessary data - from the beginner they are not, and you send him in the wrong direction.

"Exceptions is a bad name. Confusing. Unsuccessful. Actually behind this alternative flow control" - obviously not, because in addition to changing the control flow there is something else and all around intended for unique situations. Accordingly, your response will confuse the beginner. You yourself are confusing the purpose and implementation. - laury.Schup commented on March 23rd 20 at 19:44
@laury.Schup, Yes, small dog puppy to old age.
You yourself are confusing the purpose and implementation.
Tie. - Tianna.Hessel commented on March 23rd 20 at 19:47
@laury.Schup, @Tianna.Hessel, both deuces. The question was incredibly simple, and was only about ideological purity. You like Association, so the question was like the question "is it permissible to tosevite in academic drawing, if it is convenient and highly necessary?" The answer is "no" I am quite satisfied. Another thing, if I described an example would be some kind of pattern, or I would advise pattern would be very helpful.

And I just confirmed my own guesses: in predicates only a Boolean response, and throw an exception only in functions that use the predicate. Although combining the predicate to throw an exception (the answer Yes to the question about the pies or unfold) it would be very convenient, although incorrect from the point of view of "academic drawing".

The skilled person would have crawled into the documentation or used a search and found out.

Unfortunately, there is no documentation of answers to my questions ideological persuasion. - Stewart commented on March 23rd 20 at 19:50
@Stewart, I hope my previous comment didn't offend you.
The original response was motivated by the phrase
a year ago I started tightly burned out exceptions (because they rule)
I wanted to give you some food for thought. Of course, this refers specifically to the implementation of a destination - so the axe everywhere a nice, what wood, what else for someone ) - Tianna.Hessel commented on March 23rd 20 at 19:53
@Stewart, I don't know PHP, maybe there are other traditions.

In my opinion:
1. To throw an exception, but not as part of the main scenario of the use of the predicate (for example, you passed wrong parameters)
2. To throw an exception, but I can alter it to be not a predicate, and verification, see, for example, the answer is here:
https://stackoverflow.com/questions/4019748/progra...

It would be more convenient to write:

public function AddProduct($productId, $name, $price, $isCurrentlyInStock)
{
 Contracts::Require(__FILE__, __LINE__, is_int($productId), 'The product ID must be an integer.');
 Contracts::Require(__FILE__, __LINE__, is_string($name), 'The product name must be a string.');

instead of:

public function AddProduct($productId, $name, $price, $isCurrentlyInStock)
{
 if (!is_int($productId))
{
 throw new ArgumentException(__FILE__, __LINE__, 'The product ID must be an integer.');
}

 if (!is_int($name))
{
 throw new ArgumentException(__FILE__, __LINE__, 'The product name must be a string.');
 }


- laury.Schup commented on March 23rd 20 at 19:56
March 23rd 20 at 19:01
To treat the situation as exceptional or not is a matter of design. You can either take a predicate, but then this thing is the debt to return true or false and throw exceptions other situations - such as when memory is low.

Either check and throw an exception, but then there is no need to return true - it would not be a predicate.
No!

A predicate is a question of the seller at the store "Take?"
The answer is either Yes or no. The seller (the piece of code that calls the predicate) absolutely not interested in why "no" is not enough money, the Bank is not available, the rate of unacceptable... he just need to know to make rags or not. Why not - it is not here. - Nannie_Colli commented on March 23rd 20 at 19:04
Except maybe the lack of a price tag if, for example, adopted rules with each product must be the price tag, or perhaps start a fire. - laury.Schup commented on March 23rd 20 at 19:07

Find more questions by tags Programming