NAME
Language::LispPerl - A lisp in pure Perl with perl bindings.
SYNOPSIS
my
$lisp
= Language::LispPerl::Evaler->new();
# Load core functions and macros
$lisp
->load(
"core.clp"
);
my
$res
=
$lisp
->
eval
(
q|
(defmacro defn [name args & body]
`(def ~name
(fn ~args ~@body)))
(defn foo [arg]
(println arg))
(foo "hello world!") ;comment here
|
);
# $res is the last lisp object evaluated.
DESCRIPTION
Language::LispPerl is a pure Perl lisp interpreter. It is a fork of CljPerl that focuses on making embedding lisp code in your Perl written software straightforward.
INCOMPATIBILITIES
- From version 0.004
-
This uses Moose instead of Moo. This should not have any impact on your code, except if you have written your own role for 'Language::LispPerl::BuiltIns'. It will need to be a Moose::Role instead of a Moo::Role.
BINDING Perl functions to Lisp
Lisp <-> Perl
Here is how to bind to your own Perl functions from lisp.
This assumes that your perl functions live in My::App::LispFunctions
PURE Perlfunctions in My::App::LispFunctions:
package
My::App::LispFunctions;
sub
do_stuff {
my
(
$x
,
$y
) =
@_
;
..
return
;
}
sub
say_stuff {
my
(
$x
,
$y
) =
@_
;
..
return
$string_or_number
;
}
sub
is_stuff {
..
# Note that here we return a raw lisp object.
return
Language::LispPerl->true();
}
Binding to these functions in myapp.clp (living in share/lisp for instance):
;; These lisp binding functions will live
;; in the namespace
'myapp'
;; Note that you need core.clp to be loaded in the Evaler.
(ns myapp
(defn
do
-stuff [x y]
(.My::App::LispFunctions do_stuff ^{:
return
"nil"
} x y ))
(defn
say
-stuff [x y]
(.My::App::LispFunctions say_stuff ^{:
return
"scalar"
} x y ))
(defn is-stuff [x y]
(.My::App::LispFunctions is_stuff ^{:
return
"raw"
} x y)))
Usage in lisp space:
(
require
"myapp.clp"
) ;; Or in Perl
$lisp
->load(
"myapp.clp"
);
( myapp
#do-stuff .. .. ) ;; Note the myapp# namespace marker.
Importing and using any Perl package (without prior binding)
An example which creates a timer with 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)
Implemeting your own native Lisp functions
.TBC.
This lisp implementation
Atoms
* Reader forms
* Symbols :
foo, foo
#bar
* Literals
* Strings :
"foo"
,
"\"foo\tbar\n\""
* Numbers :
1, -2, 2.5
* Booleans :
true, false . Or from Perl: Language::LispPerl->true() and Language::LispPerl->false()
* Nil :
nil . Or from Perl: Language::LispPerl->nil();
* 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 lisp 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 :
* ! not :
(! 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 ...]}
(.Language::LispPerl
"foo"
)
(.Language::LispPerl
^{:
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)
* quote : Returns the
given
list as is without evaluating it
(quote (+ 1 2 )) -> (+ 1 2)
Core Functions (defined in core.clp)
*
use
-lib : append path into Perl and Language::LispPerl files' searching paths.
(
use
-lib
"path"
)
* ns : Language::LispPerl 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")
PERSISTENCE
Since V0.007, you have the possibility to 'freeze' the evaler into a pure perl data structure, and defrost it later on to execute some code in the same evaler state.
Usage:
my
$lisp
= Language::LispPerl::Evaler->new();
# Load core functions and macros
$lisp
->load(
"core.clp"
);
$lisp
->
eval
(
q|(defn square [a] ( * a a ))|
);
my
$perl_hash
=
$lisp
->to_hash();
# Store this pure perl hash somewhere in your favourite format.
# Hint: compress its representation as it can be quite big.
# Then later on:
my
$new_lisp
= Language::LispPerl::Evaler->from_hash(
$perl_hash
);
my
$res
=
$new_lisp
->
eval
(
q|(square 2 )|
);
SEE ALSO
AUTHOR
Current author: Jerome Eteve ( JETEVE )
Original author: Wei Hu, <huwei04@hotmail.com>
COPYRIGHT
Copyright 2016-2017 Jerome Eteve. All rights Reserved.
Copyright 2013 Wei Hu. All Rights Reserved.
ACKNOWLEDGEMENTS
This package as been released with the support of http://broadbean.com
LICENSE
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.