Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

RFC: IPerl - Interactive Perl ( read-eval-print loop )

by mseabrook (Beadle)
on Feb 03, 2007 at 01:54 UTC ( [id://598039]=perlmeditation: print w/replies, xml ) Need Help??

I've put together a simple script (module, really) that implements a REPL for perl. I'm sure most are familiar with the term, but for those that aren't, the idea is that the script reads an expression from the user, evaluates the expression, and finally, prints the result. The script then repeats the process.

Some trivial examples:

iperl> join " ", sort qw( squash apple turnip ) = apple squash turnip iperl> 8576275 / 3326 * 5.5 = 14182.0542693927 iperl> sub double { my $n = shift; $n * 2 } iperl> double 2 = 4 iperl> double double double 2 = 16 iperl>

I've found it to be invaluable for testing small snippits of code, calling methods in package modules, and benchmarking subroutines and module load times.

I'm considering submitting this to CPAN but I'm hesitating. I'm hesitating because I haven't seen anything like it there and it's the sort of thing that a lot of programming languages either ship with, or acquire quickly (examples: ruby, python, haskell), so I feel like there should already be an implementation (or six) out there that everyone's using.

Anyways, if you fine folks think this will be useful, I'd love to hear your suggestions on how to improve the interface and the implementation. I haven't packaged up the source code into an easily digestable tarball yet, but the POD documentation is available here.

On the other hand, if I'm re-inventing a wheel, please direct me to the original prototype. I'm sure it rolls better. :)


BTW, this is my first post. I apologize if it's in the wrong section or is generally un-monklike.

Replies are listed 'Best First'.
Re: RFC: IPerl - Interactive Perl ( read-eval-print loop )
by liz (Monsignor) on Feb 03, 2007 at 11:08 UTC
    You also might want to take a look at Zoid:
    A modular Perl shell written, configured, and operated entirely in Perl. It aspires to be a fully operational login shell with all the features one normally expects. But it also gives direct access to Perl objects and data structures from the command line, and allows you to run Perl code within the scope of your command line.

    Liz

Re: RFC: IPerl - Interactive Perl ( read-eval-print loop )
by BrowserUk (Patriarch) on Feb 03, 2007 at 11:07 UTC

    I love my REPL and I use it all the time.

    I've added all sorts of things, like uses for my favorite utilities (eg.List::Util); aliases for stuff (!....;; => system 1, ...); etc. As I get new ideas, I try them out. Anything that interferes, I discard. It really is the single most used Perl tool I have.

    But I wouldn't want to try and formalise it; and document it; and maintain it to the standard that would be required for me to consider releasing it for others to use. At that point, it would become a burden on my time, rather than the productivity tool it currently is.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: RFC: IPerl - Interactive Perl ( read-eval-print loop )
by davidrw (Prior) on Feb 03, 2007 at 04:21 UTC
Re: RFC: IPerl - Interactive Perl ( read-eval-print loop )
by ferreira (Chaplain) on Feb 03, 2007 at 17:20 UTC

    Once I asked about read-eval-print loops for Perl in the Roma-pm mailing list.

    dada gave me some excellent hints in his reply which I dare to transcribe here:

    A pair of links:

  • How can I use Perl interactively? In short: use the debugger.
  • Is there a Perl shell? Excellent pointers.

    Reinventing wheels is a good thing, if only for sport and self-learning.

      • Thanks!
    Re: RFC: IPerl - Interactive Perl ( read-eval-print loop )
    by jdporter (Paladin) on Feb 03, 2007 at 17:10 UTC
      BTW, this is my first post. I apologize if it's in the wrong section or is generally un-monklike.

      I think you did just fine, and I upvoted your post to put my money where my mouth is (so to speak). The replies you got I think are valid come-backs, but even so, making a y/perl/repl/ is a worthy project. If/when you get it to a releasable point, you could post it in Code Catacombs.

      A word spoken in Mind will reach its own level, in the objective world, by its own weight
    Re: RFC: IPerl - Interactive Perl ( read-eval-print loop )
    by Jenda (Abbot) on Feb 03, 2007 at 16:06 UTC

      You did not look well enough. There are several similar scripts and/or modules already. My PSH.pm, the Psh.pm that's on CPAN (they were quicker with releasing it, which one is actually older is a question) and I'm sure there are more.

        Thanks for the feedback, people.

        I'll more than likely just keep my implementation to myself and continue to improve on it. It's unlikely that it offers any additional features that would make it a more compelling solution than the debugger or some of the other scripts/one-liners mentioned here, and if and when I does, I'm sure it will be superseded by whatever perl6 ships with. :) It's still a fun bit of code to tinker with, though.

        Anyways, I would like to show how I implemented a couple of the features with the intent of finding out if there's a better way. If this is falling out of the realm of a "meditation", please feel free to ignore or delete this node.

        The first 'feature' is the ability to define variables with my() and have them continue to exist outside the scope of the eval block.

        The module uses a command filtering system. Users can register new filters by way of a "mixin" module, or with their ~/.iperlrc file.

        The "globalvars" mixin module turns top-level lexical variables into package globals by changing my() to our() before your code is executed. Kinda lame, huh? :) Anyways, the effect is that you can write code like this:

        iperl> my $foo = "abc" = abc iperl> do { my $bar = "def" } = def iperl> print $foo abc = 1 iperl> print $bar Use of uninitialized variable in...

        Is there a more sane way to do this? Is it possible to safely promote a lexical variable to a scope one level up? Or perhaps, to some form of sandbox scratchpad that won't pollute the module's table (which this currently does)?

        The other feature that I'd like some feedback on is the "benchmark" mixin. It can be used to benchmark each statement that's executed.

        iperl> use IPerl::Mixins::Benchmark iperl> benchmark_on() iperl> use time_consuming_module 4 wallclock secs ( 1.58 usr + 0.19 sys = 1.77 CPU) iperl>

        The module uses Hook::LexWrap to register pre and post routines. The pre routine creates a timer, and the post routine creates a second and displays the diff between the two.

        Hook::LexWrap seems to work well for this, but I'm wondering if there's a better way? My goal is to keep the additional features as unobtrusive as possible and to effectively keep them out of the base IPerl.pm module.

    Re: RFC: IPerl - Interactive Perl ( read-eval-print loop )
    by dragonchild (Archbishop) on Feb 03, 2007 at 02:42 UTC
      Look up the Perl debugger.

      My criteria for good software:
      1. Does it work?
      2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
        Look up the Perl debugger.

        Ahh.. no... it hurts my eyes!!!

        But seriously, a debugger is so not a REPL. Take this perl debugger session for example:

        DB<1> my @foo = 1 .. 10; DB<2> print join ", " => @foo;
        I get no response when I create a variable. Then when I try to use it, nothing happens. Is it not in scope anymore? Did an error occur? What is going on? How can I test my code snippets if I get no feedback?

        Yes, yes, I know, with some arcane commands and such I can get the debugger to do those thing, but why should I have too? Just consider REPLs in other languages:

        Here is Ocaml:

        # let foo = [ 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; ];; val foo : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] # List.iter (fun x -> print_int x) foo;; 12345678910- : unit = ()
        Here is Ruby:
        irb(main):001:0> foo = 1 .. 10 => 1..10 irb(main):002:0> foo.each {|x| print x } 12345678910=> 1..10
        My python/LISP/Haskell skills are way to rusty this early in the morning (before coffee too!) to write a working example, but I think I have made my point. Why should I have to work (and remember a series of arcane commands) to get what other languages give me for free?

        -stvn

          Drop the "my". The @foo you created and assigned to was local (erm ... lexical) to that one line! There is no way I know of to keep the lexical variables in scope for several separate REPL iterations.

          Try using "my" in a REPL and you won't fair any better.

          Yes, yes, I know, with some arcane commands and such I can get the debugger to do those thing, but why should I have too?

          Yes, yes, I know, if one bothers to even take a few minutes to look up just the barest of information about these "arcane" commands, one would likely quite quickly find "x" which is all that is needed to make "perl -dex" a REPL. But why bother when one can instead spend that time composing a node to demonstrate how little one knows about the debugger and how uninterested one is in learning more. :)

          % perl -dex DB<1> x @foo= 1..10 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 DB<2> x "@foo" 0 '1 2 3 4 5 6 7 8 9 10' DB<3>
          But seriously, a debugger is so not a REPL.

          No, it is much more useful. It is just trivial to use it as a REPL and is always handy on any standard Perl installation.

          A REPL is useful for experimenting. A debugger is also useful for experimenting but is even more useful for experimenting in the context of the middle of some script or module code.

          When I wrote each Win32API:: module I would use the Perl debugger to experiment with the API that I had just wrapped in order to document it properly (the official API documentation was usually vague about several interesting points, for example).

          - tye        

        Thanks. I was aware of the debugger, but it seemed awkward to use. I'll spend some more time with it.
        And, just alias iperl to perl -de 0 to save a few characters.
    Re: RFC: IPerl - Interactive Perl ( read-eval-print loop )
    by Anonymous Monk on Aug 05, 2012 at 13:20 UTC

      FWIW, this did make it onto CPAn, see App::REPL - A container for functions for the iperl program

    Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Domain Nodelet?
    Node Status?
    node history
    Node Type: perlmeditation [id://598039]
    Approved by Zaxo
    Front-paged by Arunbear
    help
    Chatterbox?
    and the web crawler heard nothing...

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

      No recent polls found