Friday, January 11, 2013

Fibonacci speed and exponential growth

For the fun of it I wrote a fibonacci algorithm in:
  • C
  • Lisp
  • Clojure
  • Python
and tested their execution speed.

The result is not surprising, and the chart below is a clear reminder that it's not the speed of the language, it's how good your algorithms perform (at least when exponential growth can be expected).

The slowness of the Clojure tests must be the JVM startup time. I know Clojure and Lisp can be compiled, here neither are.

Thar fibonacci algorithm used here are simple and recursive:

def fib(x):
    if x<=2: return 1
    return fib(x-1)+fib(x-2)

better algorithms for this exists, and i can highly recommend looking at the LiteratePrograms if you are interested in this: 

http://en.literateprograms.org/

Tuesday, August 28, 2012

Scan path example

Lisp example scanning a path and subpath for php files inside media or image folders, changed within the last 24 hours.

Shows off mail, command line, compiling and more.

(ql:quickload "cl-fad")
(ql:quickload "cl-smtp")
(ql:quickload "split-sequence")
(ql:quickload "command-line-arguments")
(ql:quickload :log4cl)

;
; helpers
;

(defmacro aif (test-form then-form &optional else-form)
    "Anaphoric Macro
    makes it possible to use value of if calculation without let assignment first"
    `(let ((it ,test-form))
        (if it ,then-form ,else-form)))

(defun find-part (part sequence)
    "Find part as as substring in sequence elements, return first occurence or nil
    (find-part \"abc\" (list \"x\" \"yabc\" \"z\")) ==> (list \"yabc\" \"z\")"
    (member part sequence :test (lambda (a b) (search a b))))

(defun get-cmdline-opt (name) 
    "Handle arguments like -x y -p w
    (get-cmdline-opt -x) => y"
    (second (member name  (command-line-arguments:get-command-line-arguments) :test 'equal )))

(defun split-and-lower (str)
    "Lowercase and split around / and return all but first item"
    (cdr (split-sequence:split-sequence #\/ (string-downcase str))))

(defun file-age-days (path)
 (/ (- (get-universal-time) (file-write-date path)) (* 60.0 60.0 24.0) ) )

;
; scanning
;


(defun file-scan (path)

 (let (files)

     (defun scan-files (path)
                    (if (null path ) 
                        (log:info "no path supplied")
            (cl-fad:walk-directory path 'check-file)))

     (defun check-file (pathname)
         (check-parts pathname (split-and-lower (namestring pathname))))

     (defun check-parts (pathname parts)
         (aif (find-part ".php" (cdr (find-part "media" parts)))
                        (prog ()
                            (if (< (file-age-days pathname) 20)
                                ;(format t "found ~a in ~a~&" it pathname)
                                (push (namestring pathname) files)
                            ))))

                (scan-files path)
                (return-from file-scan files)
 ))

(defun generate-report (files)
 (format nil "Suspect files found:
~% ~{ - ~a 
~% ~}" files))

(defun send-report (files recipient)
    " Accepts a list of filenames. Builds an apropriate mail and send it "
    (log:info "sending mail")
    (cl-smtp:send-email "mail.infoserv.dk"
        "msj@infoserv.dk" recipient
        "Suspicious files" (generate-report files)
        :extra-headers '(("Content-type" "text/html; charset=\"iso-8859-1\""))
        :authentication '("msj@infoserv.dk" "******")
        :port 366
       )
    )

;
; main
;

(defun main ()
    (aif (get-cmdline-opt "--path") 
        (send-report (file-scan it) "msj@infoserv.dk")
        (format t "supply a path using --path path")
     )
    (quit))

(log:config :daily "log.txt")
(main)

(defun compileme ()
    (sb-ext:save-lisp-and-die "scandir" :executable t :toplevel 'main :purify t))

Friday, August 10, 2012

Common Lisp error handling example

; Error  handling example.

(define-condition some-error (error)
    ((what :initarg :what :initform "something" :reader what))
    (:report (lambda (condition stream)
                        (format stream "Agh! ~@(~A~) error." (what condition))))
    (:documentation "Some-error condition."))

(defun ignore-some-error1 ()
 " Restart function "
 (print "some error 1")
 T)

(defun function-with-error ()
    " Test function which generate an error. Called directly this will start the debugger/repl. "
    (restart-case (error 'some-error :what "test")
          (use-value (value) value) ; first restart function
          (ignore-some-error1 () (ignore-some-error1)))) ; second restart function

(defun higher-function ()
    " This funtion calls a function which contains an error, but invokes the desired restart.
    Other higher-functions could select different restart or none at all, so the behaviour of 
    the function-with-error under error conditions is controlled on the higher-functions level. "
    (handler-bind ((some-error
                  #'(lambda (c)
                      (invoke-restart 'ignore-some-error1))))
                      (function-with-error )))

Wednesday, July 11, 2012

Starting on Lisp

I'm a Python programmer. But you should never stop learning!

I'm using OSX and heavily into webdevelopment, so i used Homebrew to install Lisp and the Hunchentoot webserver.

The procedure is:

  1. Install Homebrew
  2. Install SBCL using Homebrew
  3. Install Quicklisp
  4. With quicklisp its easy to install the Hunchentoot lisp webserver

Start a Hunchentoot webserver:

(hunchentoot:start (make-instance 'hunchentoot:easy-acceptor :port 4242))





Monday, September 21, 2009

Watch folder for change


import os
import sys
import time

import win32file
import win32event
import win32con

ACTIONS = {
1 : "Created",
2 : "Deleted",
3 : "Updated",
4 : "Renamed from something",
5 : "Renamed to something"
}
FILE_LIST_DIRECTORY = 0x0001

path_to_watch = u"d:\\test"
path_to_watch = os.path.abspath (path_to_watch)

print "Watching %s at %s" % (path_to_watch, time.asctime ())

FILE_LIST_DIRECTORY = 0x0001
hdir = win32file.CreateFile (path_to_watch,
FILE_LIST_DIRECTORY, win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE,
None, win32con.OPEN_EXISTING, win32con.FILE_FLAG_BACKUP_SEMANTICS, None)


while 1:

results = win32file.ReadDirectoryChangesW (
hdir, 1024, True,
win32con.FILE_NOTIFY_CHANGE_FILE_NAME |
win32con.FILE_NOTIFY_CHANGE_DIR_NAME |
win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES |
win32con.FILE_NOTIFY_CHANGE_SIZE |
win32con.FILE_NOTIFY_CHANGE_LAST_WRITE |
win32con.FILE_NOTIFY_CHANGE_SECURITY,
None, None
)
for action, file in results:
full_filename = os.path.join (path_to_watch, file)
print full_filename, ACTIONS.get (action, "Unknown")

Sunday, July 6, 2008

Django for CMS, Part 2

I have previously had doubts about the benefits of using Django as a framework for a CMS. I still have my doubts but after working with Django I might be about to change my mind.

The last year or so I have completed 4 projects using Django. 3 out of 4 projects was completed in time with a result that satisfied the customer. All 4 projects of cause of a higher quality that could be accomplished without the use of a framework.

But Django is not an easy framework to use. Even though the basic usage of the framework if simple, it takes time to master more complex tasks. Or what really takes time is to research the topic and discover the correct way to handle the task from within the framework.

But non the less, it's a greate framework!

So, why choose Django as the framework for a CMS? Here are some points:

1. It's easy to catch and URL and map it to a page-like object.

2. There are more and more "off the shelf" plug-and-play Django applications which could easy be integrated into the CMS.

3. Easy to write new CMS extensions as just another application.

4. Build-in json generator to ease communication with client side javascript.

So, after I have really gotten to know Django I feel that it might be the right choice for a CMS. And as Django is slowly getting to a stable version 1.0 and having got the Google stamp of approvel (used in Google App Engine), it might just be time to start.

Wednesday, July 11, 2007