A second installment of my attempt to code erlang-style concurrency abstraction in haskell. The effort in part I, was a bit short of the mark. Here I try to address some of the shortcomings, while leaving others open.
The main problem was that the receiver could escape outside of the process, which can cause various hard to debug mayhem. What will happen if two different threads receive data from the same channel? Yes, it might be intentional, but you could always duplicate a channel for that. What if it is a bug? What if it is a piece of malicious code? Better safe than sorry.
I'm on a learning haskell journey. But reading someone else's code and thoughts while educational is not that enlightening. Anyway, to cut the long story short:
So this is how ended with Why not try my hand at erlang style concurrency. The best thing about it is that it aligns nicely with an individualistic view of the world. I can write sequential code to do something, which from time to time communicates with the rest of them, while the rest of the time doesn't really care.
Erlang implements lightweight processes with asynchronous messaging. The cool twist it puts on it is having reception guards - if a message is not matched by the guard conditions it stays in the mailbox (channel), and the rest of the messages are scanned. The first matching message is removed from the mailbox, the remaining messages are left in the mailbox in arrival order.
http://code.google.com/apis/opensocial is out. But what does that mean?
It is reffered to as a fightback against the facebook api. I read somewhere claims that Facebook API is 98% open, Open Social 100%.
That might be true, depends on your definition of open. It is a step in the right direction. I'm not sure if you can adhere to the api, but bypass google services completely. Need to read it, touch it see it. If the API is actually server/vendor/social network platform agnostic then it is definitely a big step in the right direction, and the numbers are not as above but more like 50-100. Especially with the prospect of weird and wonderful mashups between niche networks.
The privacy and security issues will rise exponentially, but they are solvable and there is a bit more understanding in the general populace.
control resumed inspired me to take a small exercise.
"Code a minimal approximation of the python yield operator based generators"
Here follow the results I managed to get with help from Matthias Felleisen, via the plt mailing list. You can see the non-edited exchange via the mailing list archives and control and macors. All control&prompt are forms specific to plt scheme's control.ss module. The first attempt looks something like this:
(require (lib "control.ss"))
(define (make-step)
(define (control-state)
(yield 1)
(yield 2)
(yield 3)
'finished)
(define (yield value) (control resume-here (set! control-state resume-here) value))
(define (generator) (prompt (control-state)))
generator)
(define step (make-step))
(step) (step)
It does the job. Kind of. For me the interesting bit is how the interplay of prompt and control achieve maintaining the current state of execution before the return and allowing to continue from that interruption. It can be done with call/cc but it looks a helluva a lot more complicated and is far more unreadable.
There is a problem with the code above though. As Matthias notes in his email:
LESSON: never 'test' by running things at the top-level prompt. It IS a prompt. -- Matthias
So comes version 2:
(require (lib "control.ss"))
(define (make-step)
(define (control-state)
(yield 1)
(yield 2)
(yield 3)
'finished)
(define (yield value)
(control resume-here
(set! control-state
(lambda () (prompt (resume-here))))
value))
(define (generator) (prompt (control-state)))
generator)
(define step (make-step))
(equal? '(1 2 3) (list (step) (step) (step)))
control-state is a variable holding a reference to a function with no arguments, doing what the python function would do. yield is a variable holding a reference to a function which does the interrupt magic. generator is a variable holding a reference to a (sugary) function which does the initial step.
The logic of the above algorithm is roughly as follows - mark thy state, do what you need to do, when you encounter control stop, remember your state by wrapping it in a function (resume-here), remember where do you what to continue from ( the set! control-state ...). Notice that the value of control-state is replaced. This is possible since the resume-here continuation is a function and a first class value.
So what next. Boilerplate code is tedious to write. And there is a lot of boilerplate code there. And every function, which needs to follow this recipe, will need to duplicate it.
So scheme macros to the rescue. It is not a trivial problem. A 'generator' function can look something like this:
I know that I often express myself in an overcomplicated way. I hope I don't do that in code. I'm really amased how people overcomplicate stuff in their minds. This particular rant is triggered by me wandering around the net flicking design patterns in php web pages.
Guess what? They are complex beasties. With multiple hierarchies of classes doing loads of complicated stuff over a lot of lines of code.
Take a look for example at Observer Pattern. Actually not a very bad code. Still on the big side. Still maintaining the dual observer/observed 'magic' separation. Compare it with this hooks implementation, the code at the bottom of the page. The latter is designed for a more complex scenario, i.e to mimic aspects in php, but still manages to be simpler.
But the best example, I suppose, is how do you code a strategy pattern in php? A typical code would be something like Strategy Pattern. Not a bad code. Well described, documented, etc... But wait! A startegy is:
The Strategy pattern defines an object that represents an algorithm for a particular task.
But algorithm == function (or method), isn't it? So the variable function problems is I think this should do it. Yep, for complex strategies you might need to compose stuff, but still there are surely better ways, rather than having these long hard java/c++/... inherited ideas.$func = "a_function";
...
$func()
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();
delay s m =
:init
list/fill buffer s m
result = first buffer
buffer = tail buffer ++ s
result
delay-line signal =
signal + delay signal m
synth f e =
:init
s = 0
s = osc (f + e * delay m s)
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.
If anyone is interested - here is a version extracted from svn of dependency.inc. There are example uses in drpkg.
It provides an api to parse and process dependency info - no storage - that is a separate concern. You have a tree walker with callbacks + a bunch of cosmetic functions.
It is generally self-explanatory.