Most of my work on this is on paper, and some code sketeches. There quite a few non-trivial issues, and hard decisions to be made. Since I have the knack of loosing or recycling the various paper bits lying around, I decided to keep at least some of them in my diary, aka this blog.
Without going into theoretical details, some of which are quite alien to me, I'll try to describe some of the challenges that pattern patching rewriting macros might pose for a language like php. After brief explanation what kind of a beast is this, I try to explore some of the finer points, which might cause problems. The intent of this post is to sketch a design and highlight some of the possible issues.
call_user_func('a_callback_function');
call_user_func(array('AClass', 'aCallback'));
call_user_func(array($obj, 'aCallback'));
$callback = 'a_callback_function';
$callback();
$callback = array($obj, 'aCallback');
$callback();
What can we use this for? The most obvious and straight forward this is a lightweight state pattern implementation -
$a_thing()
Will behave differently depending on the value of the $a_thing variable, it's state. Another way to look at php callbacks is as proxies for 'real' functions, class or object methods.
Oh, let's not forget is_callable, it's a very useful little number.
The facility of PHP objects to encapsulate a state and us being able to access this state later can be used to turn them into functions. Let's consider:
class aClass{
var $state;
function get() { return $state; }
function next() { $state=random; }
function callbacks() { return array( array($this,'get'), array($this, 'next'));}
}
$obj = new aClass();
list( $random, $next_random ) = $obj->callbacks();
echo $random();
echo $next_random();
I've just uploaded into the bryght svn a basic filter, actually a couple of them (I was lazy). They parse a php file, and output (leave out in the case of the no_filter), all functions starting with a given prefix.
I've done it in order to be able to play with separate theme_xxx files.
usage:
vlado:~$ no_filter function_prefix php_file
read the php_file, print it to stdout, leaving out all functions starting with function prefix.
vlado:~$ yes_filter function_prefix php_file
read the php_file, print it to stdout, leaving out all functions not starting with function prefix.
both filters know about associated comments, etc...
These unfinished series or articles colloects some of my ideas about the programmeable web. I don't pretend them to be original, exclusive or useful to anyone but me. Although I hope so.
Here comes a sample test suite (it is too long, so only the beginning features in here) for the any/types, I described earlier. I like the clenliness of the schemeunit library. It features a rich set of assertions, simple but powerful grouping and both text and gui result interfaces. In order to use it you need plt scheme. Then you can grab the unit test suite from planet:
(require (planet "test.ss" ("schematics" "schemeunit.plt" 1 2)))
The code here shows testing only the any/text type and all relevant auxilary functions, using this datatatype. Looking at the code, it could be turned into a macro, so we could generate type tests automatically, rather than writing this long code..
This is an experiment to some 'atomic' types in scheme. It was tested only in plt scheme.
The basic idea is that we need some 'atomic' types, from wich to construct everything else in a web cms - users, content nodes, etc... The base field types defined here are - text, stext (short text), date, integer and float.Each field type is a closure, in which some properties, getters, setters and type-checkers are defined.
To define a new field type use the make/any/type macro. In the second part of this code snippet you will find a series of type definitions and helper functions. I quite like how this looks in scheme. I'm surprised actually. This ended up as a very cute OO-like code.
minor imporvements - Rev 4 - vlado (2 file(s) modified)minor imporvements
[relations svn]
As it says on the box minor improvements. Actually the changes are a mockup of some of my ideas for better/proper database abstraction, and a variation on some of Adrian's model thoughts.
sqlgen_join(
// functional form
sqlgen_table('n'=>'node'),
//array(ish) form
array('r'=>'node_revisions'),
// the join constrains, defines the new relation
sqlgen_constraints(
array('node_revisions'=>'may be null'),
sqlgen_and(
sqlgen_eq( arg('node','nid'),arg('node_revisions','nid') ),
sqlgen_eq( arg('node'=>'vid'),arg('node_revisions','vid'))
)
),
//result filtering
sqlgen_cond( sqlgen_eq(arg('node','nid'),$nid))
);
This is the functional form. It provides a good abstraction. It is independant of the underlying structure. In my opinion it has better code readability. Can be thoroughly unit tested.
$view=array(
'*'=>'node_revisions',
'*'=>'node',
'name'=>'user',
'#cond'=>array(
'#op'=>'AND',
array(
'#op'=>'eq',
array('node','nid'),
array('node_revisions','nid')),
array('#op'=>'eq',
array('node','vid'),
array('node_revisions','vid')),
array('#op'=>'eq',
array('node','nid'),
'#param'=>'node_view_id')
)
);
The array form, can easily become a mess. It is faster using arrays, rather than using functions to generate them, but could be daunting.
Both cases provide a close native equivalent to s-forms in php. Although you have eval(), the native php syntax is not as easily manipulateable as in lisp.
Still both forms have a significant advantage over 'embeded SQL'. We can get native php expression of the concepts in the db. We can optimise the queries, based on both data knowledge and database backends. Database independence is obvious. No rewrite_sql hacks. So things like coding a new/custom permission system becomes a breeze. Content type mashups, view/form remixing becomes possible.
As I've said this is just a mockup.
updated the comments in the functional form for readability
Upgraded and reskinned the IPROMS conference website.
While there is still some polishing to do on the visuals, the overall design will remain as it is. I will need to put new functionality there. At the moment I'm experimenting with a few approaches to importing OOo Impress presentations. That is a challenge which needs to be solved, but I'm still not sure what is optimal. The Open Document standard is a weird beast, I think a weird bad beast. I wish I could use docbook for this purpose, but that is a dream, which won't come true.
I realised that I need to demo, coming soon in flesh, why I'm doing the relations the way I do, and why I have these strange concepts.
Let's start with an example in KIF, the example is lifted from the KIF draft proposed American National Standard (dpANS).
(defrelation number (?x) := (or (real ?x) (complex ?x)))
What does it mean? Well, is number(x) will be true if x is either a real or complex number. Number is a relation.
Generally speaking we have two ways to define a relation or function - either explictly defining all possible/known cases, or by using some procedure to produce them.