Inércia Sensorial

05 de December de 2011

Leiningen, ClojureScript e REPL no navegador

Filed under: Clojure,Javascript — Tags: , — inerte @ 07:48

REPL do Clojure no navegador http://nakkaya.com/2011/12/04/leiningen-clojurescript-and-browser-repl/

21 de September de 2011

Clojure script to parse IIS logs from a directory and show slowest pages

Filed under: Clojure — Tags: , — inerte @ 15:56

Just having some fun today. The code runs actually pretty fast: It reads over 1.5 million lines from 1.1GB of logs and sorts them by time-taken in 5 seconds. I bet there’s room for improvement but it was enough for my needs.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
(ns iis_log
  (:require clojure.contrib.duck-streams clojure.contrib.io clojure.string clojure.test))
 
(def #^{:doc "Where the log files reside."} logs-directory "D:/userdata/jnetto/Desktop/zina_inside/W3SVC93479707")
 
(def #^{:doc "How many lines to show from logs."} top-to-show 25)
 
;; IIS log lines starting with # are comments
(defn is-not-comment?
  [^String s]
  (not= (.substring s 0 1) "#"))
 
(defn remove-comments
  [file-contents]
  (filter is-not-comment? file-contents))
 
;; Values on logs are separated by a space. Therefore, "-" is shown as a value when there is nothing there, instead of a space,
;; which would mess up the separator.
(defn nil-if-hyphen
  [s]
  (if (not= s "-") s))
 
(defstruct token :uri :time-taken :username)
 
(defn relevant-line-info
  "Returns a map with the path + querystring, time-taken and username from a log line."
  [line]
  (let [line-tokens (clojure.string/split line #" ")
        cs-uri-stem (nth line-tokens 6)
        cs-uri-query (nth line-tokens 7)
        cs-username (nth line-tokens 9)]
    (struct-map token :uri (str cs-uri-stem (nil-if-hyphen cs-uri-query))
                      :time-taken (read-string (nth line-tokens 20))
                      :username (nil-if-hyphen cs-username))))
 
(def accesses (ref []))
 
(doseq [child (.listFiles (clojure.contrib.io/file logs-directory))]
  (println "Processing" child) ;; Just for debugging purposes, to show something is happening
  (let [file-contents (clojure.contrib.duck-streams/read-lines child)
        file-without-comments (remove-comments file-contents)
        tokens (map relevant-line-info file-without-comments)]
    (dosync (alter accesses concat (take top-to-show tokens))))) ;; We 'take 'top-to-show here as an optimization. If we will print
                                                                 ;; only top-to-show, why take more from each file?
 
;; Until here it's actually pretty fast. 'sort-by and 'reverse are actually the slowest parts of this script.
(doseq [line (take top-to-show (reverse (sort-by :time-taken @accesses)))] 
  (println line))

20 de April de 2011

Pong in Clojure

Filed under: Clojure — Tags: — inerte @ 20:14

Me and Cesar Canassa decided to create a game. I suggested a roguelike, which we will build eventually, but as both newbies in game development, we are going to start small.

With Pong.

In the last couple months I have been teaching myself some Clojure, and said to Canassa I would like to try writing Pong using it. Now here’s where his personality shines: He had never written a single line of Clojure, but said “sure!”. Later on, while researching about functional programming, he mentioned how he had read in several places how one of the few areas of development where this paradigm is not recommended is… game development.

Ooops. Too late.

Beers in hands on a Saturday night, we promised to get something running. The plan didn’t go well. Our lack of Java and Clojure knowledge, and our lack of intelligence after ten beers got in the way. We managed to open a black window and draw white lines on it, but at the same time there was a sense of struggling, a fight against the language and its libraries. We were driving the car down the hill again and again.

Somehow on Sunday, Canassa created a repository on Bitbucket for Clojure Pong, and the first changesets started to roll in.

Today we finished the game. We thought about adding sound to the ball collision on racquets and walls but the game already does much more than training and learning code should do.

We are looking for criticism, specially on idiomatic Clojure. We tried to replace the usual maintaining of a “global” state in variables that is possible in other languages and paradigms, with a “game” map that flies around functions. It is a simple approach, but probably contains a lot of unnecessary overhead. Not in terms of performance, but in terms of function responsibility.

For example, the racquet collision function takes the whole game as parameter. Feels like cheating: Instead of using variables sprinkled to determine what is happening, the values are keys of “game”. It feels like we are still using state, but it is concentrated on a map structure.

But it works, and it is also probably more fun than training and learning code should be. There is a pause screen, the ball rolls slightly angled on game start and scoring, and a FPS counter.

We are going to use some of these stuff on our next project. Breakout is coming, and I will post again when we have some news.

Powered by WordPress