Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

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

by eyepopslikeamosquito (Archbishop)
on Oct 26, 2021 at 05:44 UTC ( [id://11138046]=note: print w/replies, xml ) Need Help??


in reply to Can someone please write a *working* JSON module

> Philosophically - I strongly disagree with the concept of ever using "croak" on broken input - that's a fast-track way to derail production code... but that's just my opinion (based on a mere 37 years of programming every day).

Since you have no code to show us, let's discuss your problem "philosophically".

First, as pointed out by a bona fide programming legend, programming every day for 37 years does not mean you are any good at it. The key is deliberative practice, not just doing it over and over again:

Researchers (Bloom (1985), Bryan & Harter (1899), Hayes (1989), Simmon & Chase (1973)) have shown it takes about ten years to develop expertise in any of a wide variety of areas, including chess playing, music composition, telegraph operation, painting, piano playing, swimming, tennis, and research in neuropsychology and topology. The key is deliberative practice: not just doing it again and again, but challenging yourself with a task that is just beyond your current ability, trying it, analyzing your performance while and after doing it, and correcting any mistakes. Then repeat. And repeat again. There appear to be no real shortcuts: even Mozart, who was a musical prodigy at age 4, took 13 more years before he began to produce world-class music. In another genre, the Beatles seemed to burst onto the scene with a string of #1 hits and an appearance on the Ed Sullivan show in 1964. But they had been playing small clubs in Liverpool and Hamburg since 1957, and while they had mass appeal early on, their first great critical success, Sgt. Peppers, was released in 1967.

Second, as noted at Two Different Languages: Two Similar Books (PBP and CCS), Perl expert Damian Conway and C++ experts Andrei Alexandrescu and Herb Sutter all agree that throwing exceptions is indeed a sound way to report errors:

  • PBP Chapter 13, "Throw exceptions instead of returning special values or setting flags"
  • CCS Guideline 72, "Prefer to use exceptions to report errors"

Conway further illustrates this specific Perl best practice with an illustrative example (number 8) which uses block eval and Carp's croak.

Admittedly, Exception handling in general is a difficult and controversial topic. Golang, for example, was initially released with exception handling explicitly omitted because the designers felt it obfuscated control flow - though the exception-like panic/recover mechanism was later added.

See also: Reflections on Skills of the Skillful

Replies are listed 'Best First'.
Re^2: Can someone please write a *working* JSON module
by bliako (Monsignor) on Oct 26, 2021 at 08:20 UTC
    Conway further illustrates this specific Perl best practice with an illustrative example (number 8) which uses block eval and Carp's croak.

    I must say I despise croak and I prefer the return (of complex:hash/object) values in order to signify errors or success. I disagree with Conway's subjective assertion that Constantly checking return values for failure clutters your code with validation statements, often greatly decreasing its readability. (number 8) :

    • especially when the way to check the exception is the eval. Often nested (666)!
    • from looking at Try::Tiny's source code, I can see it is just an eval wrapper.
    • Carp's manual states that croak does not return objects (as in a "proper" exception) and when it is given an object it calls die or warn which I think looses the stacktrace. A big price to pay for getting a bit more information out of the errors.
    • Consequently, using strings instead of an exception object, is one-dimensional: has error or not. Unless one resorts to string comparisons to check what error it was which is the safest way back to BASICs.
    • eval is relatively cheap if it's used once especially when the block is expensive (as NERDVANA has benchmarked) but what happens when code is full of evals for simple file-open-and-read operations? (Conway's number 8).
    • Another aspect of using the eval/croak exception handling, is how the perl debugger handles eval. If it's transparent, fine but if it produces an eyesore then there is another point to consider (I can't say: I have never used the debugger).

    The bottomline for me, is that until Perl manages proper exception handling I return error integers or hashes and avoid recommending "exceptions" (as Conway does) which are not the real thing. What's the real thing? For me, it must include objects and avoid evals.

    bw, bliako

      I won't argue in favor or against exceptions, but your points contain some inaccuracies.
      • die and croak can deliver objects to $@ quite fine. If you croak with an object, that object is passed to die and you can evaluate that object in $@ as you like. It loses the stacktrace, but then, you don't get a stacktrace by returning error integers/objects as well.
      • The debugger has no problems with eval. You wouldn't know, of course, if you never used it, but then why raise the issue?
      • Also, to clarify something you wrote in Re^4: Can someone please write a *working* JSON module: eval BLOCK does not "spawn a new interpreter".
      If you don't like the keyword eval, then you can have try/catch as of Perl 5.34. There are also several CPAN modules offering that, and of course they're all eval wrappers, because that's just the mechanism Perl always had. The point of the modules isn't about using different words, but avoiding the pitfalls with localized $@ (The docs of Try::Tiny give some details).

         If you croak with an object, that object is passed to die and you can evaluate that object in $@ as you like. It loses the stacktrace, I think I just said that.

        The debugger has no problems with eval. i did not say it has, I talked about a hypothetical eyesore, i.e. if it's not seamless, for example line numbers etc. in order to get some input from others who use it to agree or disagree. It would be useful to know your experience on the subject. The process of filing an application to express opinions about something that I don't use but it has an effect on the "croak debate" was taking too long so I thought I say that on the understanding that when the debate police intervenes I will show them the receipt which they can radio it to debate-HQ and get the OK. Sorry but nitpicking is not something I react nicely to.

        eval BLOCK does not "spawn a new interpreter" you are clarifying what exactly? "answering" is the appropriate word as I was asking (I think it spawns a new interpreter right?) after googling it without finding what the exact mechanism is. From experimenting with perlembed I got the impression, that eval_[sp]v are creating a new interpreter. I would really be interested to know the exact mechanism if you want to elaborate your answer?

        Edit: after cooling down, apologies for my tone, to all.

        thanks

      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?

        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 get all my json tools from the software that I've replicated of bliako's. Part of "tribal knowledge" is to know that M. Lehmann has left the fold. I wish there were a way to have perl know which modules are un-maintained, but one man's bug is another's feature.

      I can't say: I have never used the debugger

      How is it possible that you have never used the debugger?

        I use gdb for debugging C code but for Perl I just put print statements here and there.

        > How is it possible that you have never used the debugger?

        See also: on Debuggers (posted earlier this year in response to ... Aldebaran I see! :)

        Oh well, it seems debuggers and exception handling, also discussed in this thread, are topics people tend to hold strong opinions on that are most unlikely to change.

        > How is it possible that you have never used the debugger?

        As always definition matters.

        perl -de0 is more than just a debugger.

        ... it's also Perl's main REPL, it's pretty good for ad hoc testing and interactive demos.

        I use it regularly for that.

        Others even use it as a Perl Shell, because it's very customizable.

        Personally I almost never use it for debugging my own code ( i.e. Breakpoints, Watch-expressions, etc), because I have a unit-test mixed with debug output strategy (mostly Data::Dump 's dd and pp)

        But it is very valuable when analyzing monolithic foreign code (e.g. B::Deparse)

        Now perl -de0 is commonly known as "The Debugger" , which is causing reactions.

        Unfortunately "people with strong opinions" here have a Pavlov reflex to demonstrate their ignorance.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11138046]
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: (3)
As of 2024-04-19 17:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found