Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Re^3: Can someone please write a *working* JSON module

by Anonymous Monk
on Oct 26, 2021 at 08:48 UTC ( [id://11138052]=note: print w/replies, xml ) Need Help??


in reply to Re^2: Can someone please write a *working* JSON module
in thread Can someone please write a *working* JSON module

It doesn't have to be a dichotomy. Exceptions can be used when you need to fail the operation and jump in an overall exception handler multiple functions above in the call stack. Success/error return values (preferably when they are of different types and the compiler can make sure you're not using the success type in the error branch, a.k.a. the Optional<Success, Failure> idiom) can be used when you can check for and handle the error right away.

People who use exceptions won't argue in favour of code like the following:

eval { step_1(); 1; } or handle_error_1(); eval { step_2(); 1; } or handle_error_2(); eval { step_3(); 1; } or handle_error_3(); eval { step_4(); 1; } or handle_error_4();
That's just more typing for the same result as
step_1() or handle_error_1(); step_2() or handle_error_2(); step_3() or handle_error_3(); step_4() or handle_error_4();

On the other hand, if an error means the whole operation should be aborted and the individual steps signal that by raising an exception, we can write it as

try { step_1(); step_2(); step_3(); step_4(); } catch { handle_overall_error(); };
and still be sure that when the error happens, (1) any resources will be cleaned up safely by desctructors and (2) the following steps won't be taken.

By the way, why do you dislike eval? I mean, I don't like eval EXPR either, but what's wrong with eval BLOCK?

Replies are listed 'Best First'.
Re^4: Can someone please write a *working* JSON module
by bliako (Monsignor) on Oct 26, 2021 at 09:17 UTC

    I agree, your 1st snippet is bad form. And also the 3rd snippet looks better than the 2nd but the handle_overall_error() must include (for me) the logic of 2nd snippet in order to deduce what really happened, in which step the error really is. In theory it looks nice and compact. In practice, grouping step_1, 2 3 and 4 like this just happens in toy-cases and if they are grouped naturally like this then why not grouping them in a sub. Anyway. I get the point and thanks for the demonstration.

    By the way, why do you dislike eval? I mean, I don't like eval EXPR either, but what's wrong with eval BLOCK?

    yes I was talking about eval BLOCK as well. Micro-optimisation mostly (mea culpa), I think it spawns a new interpreter right? I am this kind of person that I hate taking the car to the corner shop because I visualise horror: the engine metals screaching, burning, rubbing together, aching and suffering just because I am in need of a cigarette. So I invariably walked until I gave it up altogether.

      I think it spawns a new interpreter right
      It definitely doesn't. eval BLOCK just pushes a 'EVAL' context onto the context stack, in a similar way that a sub call pushes a 'SUB' context, and a bare block pushes a 'LOOP_PLAIN' context. A context is just a type flag and a bit of saved state. On normal scope exit, the context is popped and the saved state restored (e.g. @_ restored on return from a sub). On an exception (die, croak etc), the perl interpreter keeps popping contexts (and restoring the saved state in each) until it hits an EVAL context or empties the context stack.

      The context stack is what caller() examines (in part).

      eval $string has a slow preceding step where it has to call the parser and compile the string into something resembling a sub, then it calls that 'sub' by pushing an EVAL context as with the block case.

      Benchmarks show that eval BLOCK has roughly the same overhead as calling a sub with no arguments.

      Dave.

        thanks that clarifies it.

      I think it spawns a new interpreter right?

      Well, eval_sv and eval_pv are related to eval EXPR, not eval BLOCK. There's obviously some performance lost, but not as much as PerlInterpreter * my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, argc, argv, (char **)NULL); perl_run(my_perl); perl_destruct(my_perl); perl_free(my_perl);. New interpreters are constructed for every thread, with tied variables handling access to shared variables, but I don't think a separate interpreter is needed for every eval. eval EXPR additionally spends time in the parser, but eval BLOCK uses the already-parsed data structures.

      I've spent a few minutes skimming the source. Perhaps the die() destination and the use feature 'try' entry point could be a good place to start, but I'm not enough of an expert to judge what's really happening here. Though I'm sure it's the same interpreter.

        thank you for this answer.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11138052]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (2)
As of 2024-04-20 06:36 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found