Saturday, March 03, 2007

SubX. Common Lisp Sub-eXpression language.

There are some disadvantages to using common lisp. Some of them I've mentioned in my previous post. Subx tries to improve on these or possibly eliminate some of them.
A grammar that is intuitive enough and covers the usual programming patterns isn't impossible to create. It has been and will continue to be developed in future languages. Macros allow you to extend the existing grammar at various levels. This is the case with the 'loop' macro that defines it's own iteration-language. This is one of the most complex that is offered by the standard implementation of common lisp. There are others of course like 'dotimes', 'dolist' etc. Subx tries to offer structures that are general enough to apply to usual cases and simplify overall the code. It provides a framework for creating grammars. It's based only on a few very basic concepts: operators: unary, binary and parentheses: associativity, context change parens and proper lisp parens. Using these concepts custom macros/functions can be used with a more clear syntax.

Expressions that use the subx-grammar can be used in lisp by surrounding them in []. These are just read as normal paranthesized expressions so you can use them anywhere:

(defun some-function()
[ <subx-expression> ])

(loop for x below 10 collect
[ <subx-expression> ])

Well, you get the idea.
Now, just to start on the safe side subx can be inserted in normal lisp code but also normal lisp code can seamlessly be integrated in subx. So [] can contain (<symbo|form>*) that are interpreted as lisp expressions (s-expr). So writing something like [(list 1 2)] is pretty much the same as (list 1 2) and also [(list 1 [2])] or some other nesting.

As you guessed () act as normal parens. So [(1)] isn't that legal cause (1) is not.

The third kind of parens used are {}. These represent function application. The syntax is function{<param,>*<param>}
Operators have associativity and priorities. Some are already defined: common arithmetic, some logic. Any othe operatator is considered a function.

There are a couple of operators that I've defined already. These include:
- sequencing by progn: ';'
- sequencing by forms enumeration: ':'
- list construction: ','
- function call on a form: '.'
- function call '{}'
- apply function '~'
- map '<-', mapcan '<<-', filter '<->', reduce '<=>'
- arithmetic, logical, bitwise
- assignment: '=', destructuring bind: ':='

Some basic examples:
Writing a function call:

(list 1 2)
[list 1 2]
[list{1,2}]
[apply #'list 1,2]
[funcall #'list 1 2]
[1.(list 2)]
[1.list~2]
[1.list{2}]
==> (1 2)

Applying a map:

[1..5 <- ((x) (inc x))]
[1..5 <- inc]
[1..5 <- #'inc]
[1..5 <- (lambda (x) (inc x))]
==> (2 3 4 5 6)

Filter:

[1..10 <-> oddp]
==> (1 3 5 7 9)

Reduce:

[1..10 <=> #'+]
==> 55

Ifs:

[if 1 + 2 == 3: list{1,2}: list~3]
==> (1 2)

[when 1 == 1: print 1,2,3]
==> (1 2 3)

[unless 1 == 2: print{1,2,3}]
==> 1 2 3

Nesting ifs:

[if 1 == 1:
[if 2 == 1 + 2: print{2}: print{3}]:
print{4}]

Weird add-ing:

[+ 1.+{2}.+~3.(+ 4) + 5 6]
==> 21

Weird equals:

3 == 1 + 2 == 4 - 1
==> 3

Slicing:

[..{10}@..{3}]
[[..10]@[..3]]
[(..10)@(..3)]
[..~10@..~3]
==> (0 1 2)

Loop-ing:

[for x on 1..5 <- list collect:
sum{x@[..2] <- car}] ==> (3 5 7 9 5)

Using macros:

[let ((x 9)): x = print{x + 1} + 2; x,2]
==> 10 10
==> (12 2)

[for x in 1..10 collect: x + 1]
==> (2 3 4 5 6 7 8 9 10 11)

[x = 0; while [x += 1] < 10 collect: x,]
==> ((1) (2) (3) (4) (5) (6) (7) (8) (9))

[defparameter x: 1 + 2, 4]
x
==> (3 4)

[(x &rest y) := [..5]; x, y]
==> (0 (1 2 3 4))

[f = [lambda (x): x + 1]; f{1}]
==> 2

Thursday, March 01, 2007

What about Lisp?

What about this oldy, Common Lisp? Great language overall. Some glitches here and there.

Skipping the dispute about strictly functional vs tolerable imperative, lisp is a great language for expressing yourself in the most intimate way allowed by a programming language. Using programming patterns makes a good programmer, but creating your own also makes a happy programmer.

There's a permanent need in lisp to write code in an awkward manner. This sometimes leads to frustration but most often is compensated by the sheer joy of being able to express everything as it comes to mind and not having to convert things to a preexisting grammar-enforced pattern of thought.
The main reasons for frustration that are frequently mentioned are:

1. parentheses - There's too many of them. Even with parens-match highlighting or other nifty tricks like list depth color-codes the lines blurr until you exercise your focus skill.
2. prefix notation - It's hard to get used to this. The normal pattern of thought is to apply transformations on lists from left to right. Sometimes even after gaining some experience with the prefix form (when you start feeling good about writing parens) you still think in left to right transformations so you actually do a manual conversion from left to right to prefix notation.
3. notations for symbol list creation - They get very confusing. And it's not just about the level of indirection (symbol to value stuff). When you start using macros the first thing you learn is about the back-tick operator and it's associated ',' expression evaluation. This is just crazy when used recursively.
4. list construction - When constructing lists that are not quoted you must specify every time a list construction function like list or maybe use an abbreviation like '@' (@ x 2 (@ y 5))

Any programming language that has a decent grammar (Haskell, Python, Ruby) doesn't have these problems but neither does it have the power inherent to lisp. Some of those things that make lisp better:

1. Expressions can be inserted almost everywhere in an existing code. This is why ideas can be expressed straight-forward as they come to mind.
2. Macros provide compile time AST parsing and restructuring.
3. Macros can also be considered to provide compile time lazy evaluation of expressions.
4. Uniform syntax for any kind of function/operator (the prefix notation).
5. Quoting allows having direct access to symbols. You are not forced to use strings, can manipulate literals in the code directly.

There are many others but let's just not get carried away. All these said lisp is great for being happy with yourself but not really caring about working with others. The sparseness of ready to use modules/packages creates a barrier for the beginner, too varied coding patterns creates a barrier for a possible community. Too many barriers are discouraging to brake. Those that do succeed create a "group" of solitary individuals and do not try to brake the final barrier: share what you create.

Saturday, February 24, 2007

Attribute mapper in Python

I really don't like redundancy. Mainly it's not about the kind that just makes you type more when you program. It's about concepts, having to think about some trivial stuff each and every time and not being able to perfectly focus on the task at hand. Many minor disturbances can have a nasty result (maybe just on the fun part).
I dislike programming patterns that use looping variables just because 'this is the standard way to do it'. Even functional iteration is in some cases redundant.
Some examples in python:

Do a map on list:

[fn(var) for var in list]


Here var is pretty redundant. Map is more concise:

map(fn, list)

But, when it comes to taking some attribute/calling a function on every element of a list, things get ugly for map,

map(lambda var: var.attribute, list)

but stay about the same for the list comprehension:

[var.attribute for var in list]

Something as concise as the first expression of map for attributes would be a welcome. Expressing it in python:

mapper(list).attribute

'.' is used to take the attribute because it's shorter than using a string attribute and is more intuitive.

A possible implementation:

class mapper(list):
def __getattr__(self, attr):
list.__init__(self, [getattr(x, attr) for x in self])
return self

def __call__(self, *args, **kws):
list.__init__(self, [x(*args, **kws) for x in self])
return self

Here you cannot use attributes that are methods in the list class.
The advantage can be noticed for accessing attributes that don't have a functional accesor (ie lambda x: x.attribute).

Examples of use:

mapper("aBcD").lower()
==> ['a', 'b', 'c', 'd']

class a: a = 1

mapper([a() for x in range(3)]).a
==> [1, 1, 1]

Other uses (call every function in a list):

mapper([lambda:1,lambda:2])()
==> [1, 2]

mapper("ab ac bc".split()).replace('a','x').capitalize()
==> ['Xb', 'Xc', 'Bc']

Wednesday, February 21, 2007

More than List Comprehensions. Common Lisp Loop

Now, here I was admiring list comprehensions in other languages but lisp. It seams the loop macro is more than it looks. List comprehensions are an iterative style combination of map and filter constructs. Well, with loop in lisp you can do even more. You can actually include reduce in the picture.

A helper macro to shorten our code ;) :

(defmacro for(&body body)
    `(loop for ,@body))


A small function builder that integrates reduce into loop:

(defun loop-reduce (fn)
    (lambda (l)
        (when (cdr l)
            (cons (funcall fn (car l) (cadr l))
                        (cddr l)))))

Here are the basic implementations of these three function in the loop sub-language:

Two nested maps (applied function is list):

(for x below 3 nconc
    (for y below 3 collect
        (list x y)))

and the result:
((0 0) (0 1) (0 2) (1 0) (1 1) (1 2) (2 0) (2 1) (2 2))

A simple filter (applied function is oddp):

(for x below 10 when (oddp x) collect x)

with the result:
(1 3 5 7 9)

And finally a reduce (applied function is +):

(for x in '(1 2 3 4) by (loop-reduce #'+) finally (return x))

with the result:
10

If you do:

(for x in '(1 2 3 4) by (loop-reduce #'+) collect x)

you also get the intermediary results:
(1 3 6 10)

Well, the last reduce could have been a lot easier written as:
(for x in '(1 2 3 4) sum x)
but this isn't that general (even if it works also with counting, minimizing, maximizing).

Now, isn't that nice :P

Sunday, February 18, 2007

docs.google.com

Just used a very nice feature of google docs. I was wondering for some time (just wondering not actually thinking about it) how I could make that post text box larger. And there it was all the time. Google docs offers easy integration with lots of other blog hosts.

Monday, February 05, 2007

Problems with the hard disks

Lately I've been having problems with my hard-drives. I had 2 SATA drives on a stripped RAID array and one of them broke. Here's what I did in not exactly the same order to recover my data. I'm no expert but maybe this can help somebody.

1. Check the drives with the Windows install disk (it couldn't have seen the partitions right)

2.
Check the drives with a Linux install disk (Ubuntu, Knoppix or could have used Fedora's). No big difference using "fdisk -l" to see the partitions correctly.

3. Download "Ultimate Boot CD" [http://www.ultimatebootcd.com] and burn it on a CD. You can get a basic version and a full version that also has a Linux based OS and some more programs that you can use to check disks/partitions and some other good stuff (like antiviri).
UBCD has some built-in firmware programs for physically checking your hard-disk. Use these to repair partition/fix bad sectors if possible.
If all fails try moving your hdd to a Windows system /adding a good hdd to your system and installing Windows. Next:

4. Use Partition Magic to check your hdd. If you don't care about the data on the disk fully-format your drive:
- right click on the drive to enable bad sector checking
- recreate/create partitions to fill the disk and format them
There's a bug with bad partition info in Partition Magic 8 that makes the program fail to start so use Paragon Hard Disk Manager to repartition a disk.
You can also use the Windows chkdsk or Norton System Works - Disk Doctor to check/fix the drive.

5. If the data on the disk matters to you use Get Data Back [http://www.runtime.org/gdb.htm]. If you have a broken stripped RAID try RAID Reconstructor [http://www.runtime.org/raid.htm] first to un-strip the disk first.

6. If finally you find that you have a completely unusable disk drop it and buy another. Else, try using a disk monitor like HDD Health [http://www.panterasoft.com] to notice any problems before they become too serious. This is especially nice with the SMART option enabled on the drive.

Finally I wasn't successful because the damage to one of my drives was too great.

Saturday, January 13, 2007

Log de idei

Ma gandeam sa folosesc blogul ca un repository (personal probabil).
Am folosit diverse modalitati pana acum pentru a face chestia asta. Am pornit cu word u bineinteles, dar a inceput sa ma enerveze sa ma incurc cu documentele sa nu le pot clasifica frumospe toate si sa le accesez usor mai ales ca erau multe texte mici care le scriam.
Am incercat si tree-view-ere pentru a face o ierarhie de idei pe care sa o completez frumos asa. A tinut ceva, but I moved on :P.
ca nu Urmatoarele au fost diagramele UML use cases (cu Poseidon). Cu astea poti face grafuri. Reprezentarea era mai complexa si permite relatii mai bine definite decat intr-un copacel. In principal ma interesa pozitionarea in pagina si posibiliteatea de zoom-in/out. Asta inca tine, doar ca nu prea poti scrie mult text. Si daca vrei sa adaugi notes la diagrama procesul de editare se complica.
Simteam nevoia de ceva online. Cand mai plecam pe acasa vroiam sa mai scriu cate ceva asa ca era ciudat sa tot scriu discuri sa le car cu mine inapoi in Bucuresti. Prima varianta care mi-a trecut prin minte a fost mail. Gmail-ul e destul de bun mai ales cand pui reply-uri la aceeasi chestie asa ca aveam tree-viewer-ul meu online, oarecum.
Stiam de google.com/ig (personalized home page) de ceva timp. Pe masura ce s-au adaugat noi features de genul Sticky Note (care pot fi puse mai multe / tab) am inceput sa vad utilitatea pentru creearea de structuri ierarhice de exprimare a ideilor. Din pacate nici astea nu-s perfecte. Ca prima ideea nu incap prea multe pe pagina si textul interior nu arata asa frumos ierarhizat. Apoi, vroiam sa pun o formula (care era imagine) o data. Nu prea se poate.
Uite acum am dat si de noua versiune (iesita din beta) de blogger. Se pare ca are o interfatza "chiar evoluata". Pe langa templates are si facilitatea de a edita pozitionarea elemetelor in pagina usor si multe alte features. Partea frumoasa e ca poti adauga imagini posturilor :). Si e online.
Bine acuma, exista si editoare ca Writely la care sunt online. Si astea permit toate features-urile de la un blog si plus altele pentru editare. Un fel de combinatie dintre wiki, blog, word. Nu e asa frumos sistemul de comentarii doar.
Eu inca is in cautare de un sistem mai bun de exprimare a ideilor. Voi ce folositi ?

Un inceput

Am zis ca o sa scriu in engleza blogul asta. Eh, uite ca nu a ajuns sa fie asa, cel putin pentru un inceput :P. Nu stiu de ce am ales sa fac asta. Probabil unul din motive e ca vroiam sa fiu consistent in ceea ce spun; ii zisesem unui prieten ca ar fi mai util sa-si scrie si el blogul in romana. Desi nu a urmat sfatul tot ma simt probabil constrans de afirmatii anterioare. Vad asta ca un fel de constrangere, dar s-ar putea sa existe motive ascunse pentru care consideram si inainte ca e mai bine sa scrii un blog pe romana.
In primul rand cititorii sunt prieteni sau cunoscuti si ei constituie cea mai mare parte din cei care acceseaza blogul presupun. Daca se intampla ca numarul acestora sa creasca se poate face trecerea la folosirea englezei.
Din alta privinta e foarte probabil ca puterea de formulare a ideilor in limba nativa sa fie mult superioara altor limbi preluate ulterior. Astfel, desi engleza e folosita aproape in toate documentele pe care le citesc in ultima vreme tot cea mai mare parte din formulari sunt pe romana. Se intampla ca unii termeni din engleza sa ajunga in limbajul curent. O evolutie normala a limbajului se poate zice ;)).