The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

CljPerl - A lisp on perl.

SYNOPSIS

        (defmacro defn [name args & body]
          `(def ~name
             (fn ~args ~@body)))

        (defn foo [arg]
          (println arg))

        (foo "hello world!") ;comment here

DESCRIPTION

CljPerl is a lisp implemented by Perl. It borrows the idea from Clojure, which makes a seamless connection with Java packages. Like Java, Perl has huge number of CPAN packages. They are amazing resources. We should make use of them as possible. However, programming in lisp is more insteresting. CljPerl is a bridge between lisp and perl. We can program in lisp and make use of the great resource from CPAN.

EXPORT

Lisp <-> Perl

CljPerl is hosted on Perl. Any object of CljPerl can be passed into Perl and vice versa including code.

An example of using Perl's IO functions.

Perl functions in CljPerl.pm

        package CljPerl;
        
        sub open {
          my $file = shift;
          my $cb = shift;
          my $fh;
          open $fh, $file;
          &{$cb}($fh);
          close $fh;
        }
        
        sub puts {
          my $fh = shift;
          my $str = shift;
          print $fh $str;
        }
        
        sub readline {
          my $fh = shift;
          return <$fh>;
        }
        

CljPerl functions in core.clp

        (ns file
          (defn open [file cb]
            (. open file cb))
        
          (defn >> [fh str]
            (. puts fh str))
        
          (defn << [fh]
            (. readline fh)))

Test

        (file#open ">t.txt" (fn [f]
          (file#>> f "aaa")))
        
        (file#open "<t.txt" (fn [f]
          (println (perl->clj (file#<< f)))))

An advanced example which creates a timer with AnyEvent.

        (. require AnyEvent)

        (def cv (->AnyEvent condvar))
        
        (def count 0)
        
        (def t (->AnyEvent timer
          {:after 1
           :interval 1
           :cb (fn [ & args]
                 (println count)
                 (set! count (+ count 1))
                 (if (>= count 10)
                   (set! t nil)))}))
        
        (.AnyEvent::CondVar::Base recv cv)

Documents

Reader

 * Reader forms

   * Symbols :

        foo, foo#bar

   * Literals
 
   * Strings :

        "foo", "\"foo\tbar\n\""

   * Numbers :

        1, -2, 2.5

   * Booleans :

        true, false

   * Keywords :

        :foo

 * Lists :

        (foo bar)

 * Vectors :

        [foo bar]

 * Maps :

        {:key1 value1 :key2 value2 "key3" value3}

Macro charaters

 * Quote (') :

        '(foo bar)

 * Comment (;) :

        ; comment

 *  Dispatch (#) :

   * Accessor (:) :

        #:0 ; index accessor
        #:"key" ; key accessor
        #::key  ; key accessor

   * Sender (!) :

        #!"foo"

   * XML ([) :

        #[body ^{:attr "value"}]

 * Metadata (^) :

        ^{:key value}

 * Syntax-quote (`) :

        `(foo bar)

 * Unquote (~) :

        `(foo ~bar)

 * Unquote-slicing (~@) :

        `(foo ~@bar)

Builtin Functions

 * list :

        (list 'a 'b 'c) ;=> '(a b c)

 * car :

        (car '(a b c))  ;=> 'a

 * cdr :

        (cdr '(a b c))  ;=> '(b c)

 * cons :

        (cons 'a '(b c)) ;=> '(a b c)

 * key accessor :

        (#::a {:a 'a :b 'a}) ;=> 'a

 * keys :

        (keys {:a 'a :b 'b}) ;=> (:a :b)

 * index accessor :

        (#:1 ['a 'b 'c]) ;=> 'b

 * sender :

        (#:"foo" ['a 'b 'c]) ;=> (foo ['a 'b 'c])

 * xml :

        #[html ^{:class "markdown"} #[body "helleworld"]]

 * length :

        (length '(a b c)) ;=> 3
        (length ['a 'b 'c]) ;=> 3
        (length "abc") ;=> 3

 * append :

        (append '(a b) '(c d)) ;=> '(a b c d)
        (append ['a 'b] ['c 'd]) ;=> ['a 'b 'c 'd]
        (append "ab" "cd") ;=> "abcd"

 * type :

        (type "abc") ;=> "string"
        (type :abc)  ;=> "keyword"
        (type {})    ;=> "map"

 * meta :

        (meta foo ^{:m 'b})
        (meta foo) ;=> {:m 'b}

 * fn :

        (fn [arg & args]
          (println 'a))

 * apply :

        (apply list '(a b c)) ;=> '(a b c)

 * eval :

        (eval "(+ 1 2)")

 * require :

        (require "core")

 * def :

        (def foo "bar")
        (def ^{:k v} foo "bar")

 * set! :

        (set! foo "bar")

 * let :

        (let [a 1
              b a]
          (println b)) 

 * defmacro :

        (defmacro foo [arg & args]      
          `(println ~arg)
          `(list ~@args))

 * if :

        (if (> 1 0)
          (println true)
          (println false))
          
        (if true
          (println true))

 * while :

        (while true
          (println true))

 * begin :

        (begin
          (println 'foo)
          (println 'bar))

 * perl->clj :

 * ! :

        (! true) ;=> false

 * + - * / % == != >= <= > < : only for number.

 * eq ne : only for string.

 * equal : for all objects.

 * . : (.[perl namespace] method [^meta] args ...)
        A meta can be specifed to control what type of value should be passed into perl function.
        type : "scalar" "array" "hash" "ref" "nil"
        ^{:return type
          :arguments [type ...]}
        
        (.CljPerl print "foo")
        (.CljPerl print ^{:return "nil" :arguments ["scalar"]} "foo") ; return nil and pass first argument as a scalar

 * -> : (->[perl namespace] method args ...)
   Like '.', but this will pass perl namespace as first argument to perl method.

 * println

        (println {:a 'a})

 * trace-vars : Trace the variables in current frame.

        (trace-vars)

Core Functions

 * use-lib : append path into Perl and CljPerl files' searching paths.

        (use-lib "path")

 * ns : CljPerl namespace.

        (ns "foo"
          (println "bar"))

 * defn :

        (defn foo [arg & args]
          (println arg))

 * defmulti :

 * defmethod :

 * reduce :

 * map :

 * file#open : open a file with a callback.

        (file#open ">file"
          (fn [fh]
            (file#>> fn "foo")))

 * file#<< : read a line from a file handler.

        (file#<< fh)

 * file#>> : write a string into a file handler.

        (file#>> fh "foo")

SEE ALSO

AUTHOR

Wei Hu, <huwei04@hotmail.com>

COPYRIGHT AND LICENSE

Copyright 2013 Wei Hu. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.