This is splendid. Rich Hickey is talking about OOP in second part of Clojure for Java Programmers.
At 35:40 he says: [With OOP] you’re set up to do the wrong thing. From the concurrency standpoint its complete catastrophe. It’s a disaster. It’s unworkable. Eventually you’ll die with locks. You either die trying make them work or to try to understand them or just from the stress.
I second that !!!
Recently I got an email which sugessted some people still don’t get what the VanadiumJS is all about. Here is my explanation:
> Vanadium won’t replace the need for server side validation but the client side instant notification is great for usability.
< Vanadium is not intended to replace the server-side validation. But it is not the client-side validation toolkit only. The real value of Vanadium is its ability to integrate both validations. Vanadium splits validation into two phases: testing and decoration. If, for an example, you do client-side validation vanadium performs testing on validated elements or the entire form and produces result of these tests in json format. Then it uses that structure in order to inject appropriate css classes to validated fields and their containers (decoration). On the other hand when your form is valid on client side you make a request to the server and you perform server-side validations there. Rather than rendering the invalid decorated html on the server-side you can pass server-side validation result as a description in very same json format vanadium uses and vanadium will decorate on the client-side the result of server-side tests. This philosophy make extremely easy to create plugins for web frameworks in order to have dynamic, transparent server side validation on the clinet-side. Currently I have RubyOnRails Vanadium plugin on my roadmap. Anther person is interested in developing one for CackePHP.
Said that, now I call all web developers: If you would like to create server-client-validation plugin for web-framework of your choice, I’m happy to help you in explanation of VanadiumJS quirks and magic, mentoring on different levels and in giving general advice and support.
Enjoy!
JSONERL is published.
It is simple tool for turning your erlang records into json and back.
Here is an example of the usage of jsonerl:
1
2
3
4
5
6
| -include("jsonerl.hrl").
-record(artist, {name, year_of_birth, city, photo, movies}).
Artist = #artist{name = <<"Luc Besson">>, year_of_birth = 1959, city = <<"Paris">>, photo = <<"http://is.gd/3pYJF">>, movies = [<<"Taken">>,<<"Bandidas">>,<<"Taxi">>]},
Json = ?record_to_json(artist, Artist),
Artist = ?json_to_record(artist, Json). |
the resulting json will be:
1
2
3
4
5
6
7
| {
name: "Luc Besson",
year_of_birth: 1959,
city: "Paris",
photo: "http://is.gd/3pYJF",
movies: ["Taken","Bandidas","Taxi"]
} |
The code is available at github.
I’m pleased to announce that the first version of demo site presenting my client-side validation toolkit Vanadium is on the go.
Vanadium is declarative, client-side validation toolkit. There is no need for coding. Just use simple markup in side class attributes (or if you are HTML purist you may prefer to attach it as external configuration file in json format).
E.g. for required field one can define it as: <input type="text" class=":required“/>
It also make use of Ajax. E.g checking for username availability can be expressed as:
<input type="text" class=":ajax;/username_checker/check.json“/>
Another handy feature is hierarchical validation regions, lots of build-in validator types and easy way of creating custom ones.
I’ll appreciate any comments on it.
You can give it try on VanadiumJS.com. The code is open source and available on github.
Justin Sheehy posted here his webmachine version of a small but fun web application created originally in mochiweb by Hughes Waroquier from BeeBole. Hughes posted it in a form of neat screencast tutorial. It’s worth watching.
Justin’s version is dated from October 22, 2008 and at that time webmachine version was < 1.0. Since that time the webmachine progressed and API has changed. Moreover, Justin's great example is not a single file but rather code in-lined with post prose. His code has the static content delivery mixed-up with sticky notes resource. It also contained a security issue, which is using list_to_atom bif with arbitrary arguments coming from API user, potentially opening door to blow our erlang VM’s memory up (running out of atoms).
Recently I was asked by my friend to introduce him Erlang webdevelopment. I though immediately about webmachine and the sweet sticky notes tutorial so I decided to create working code of that stuff. I have reused my static resource for webmachine resulting in having separation of Ajax API and static content delivery, reducing the original stickyNotes_webresource.erl to 18 lines of code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| -module(stickyNotes_webresource).
-export([init/1, process_post/2, allowed_methods/2]).
-include_lib("webmachine/include/webmachine.hrl").
init(Config) -> {{trace, "/tmp"}, Config}.
allowed_methods(ReqData, Context) ->
{['POST'], ReqData, Context}.
process_post(ReqData, Context) ->
Ps = mochiweb_util:parse_qs(wrq:req_body(ReqData)),
Struct = mochijson2:decode(proplists:get_value("json", Ps)),
Act = list_to_existing_atom(binary_to_list(struct:get_value(<<"action">>, Struct))),
Resp = wrq:merge_resp_headers([{"Content-Type", "application/json"}], ReqData),
Resp2 = wrq:append_to_response_body(mochijson2:encode(notes:Act(Struct)), Resp),
{true, Resp2, Context}. |
The whole thing can be found at github.
It easy to handle streams of bytes in Erlang. For example consider the following simple task:
given a stream consisting of 3-byte chunks we want to return a stream consisting of those 3-byte chunks whose first byte is zero.
This can be written in the following manner:
keep_0XX(Bin) -> << <<0:1,X:2>> || <<0:1,X:2>> <= Bin >>.
I like it, I hope you too.
[update]
Previously I thought it was undocumented feature of erlang. As Bryan kindly pointed out, one can find it documented here.
Thank you Bryan.
I’ve implemented HashMapJS, a simple hash map like implementation.
The project is located at github.
Here is the code with the usage examples:
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
| /*
=====================================================================
@license MIT
@author Daniel Kwiecinski <daniel.kwiecinski@lambder.com>
@copyright 2009 Daniel Kwiecinski.
@end
=====================================================================
*/
var HashMap = function() {
this.initialize();
}
HashMap.prototype = {
hashkey_prefix: "<#HashMapHashkeyPerfix>",
hashcode_field: "<#HashMapHashcodeField>",
hashmap_instance_id: 0,
initialize: function() {
this.backing_hash = {};
this.code = 0;
this.hashmap_instance_id += 1;
this.instance_id = this.hashmap_instance_id;
},
hashcodeField: function() {
return this.hashcode_field + this.instance_id;
},
/*
maps value to key returning previous assocciation
*/
put: function(key, value) {
var prev;
if (key && value) {
var hashCode;
if (typeof(key) === "number" || typeof(key) === "string") {
hashCode = key;
} else {
hashCode = key[this.hashcodeField()];
}
if (hashCode) {
prev = this.backing_hash[hashCode];
} else {
this.code += 1;
hashCode = this.hashkey_prefix + this.code;
key[this.hashcodeField()] = hashCode;
}
this.backing_hash[hashCode] = value;
}
return prev;
},
/*
returns value associated with given key
*/
get: function(key) {
var value;
if (key) {
var hashCode;
if (typeof(key) === "number" || typeof(key) === "string") {
hashCode = key;
} else {
hashCode = key[this.hashcodeField()];
}
if (hashCode) {
value = this.backing_hash[hashCode];
}
}
return value;
},
/*
deletes association by given key.
Returns true if the assocciation existed, false otherwise
*/
del: function(key) {
var success = false;
if (key) {
var hashCode;
if (typeof(key) === "number" || typeof(key) === "string") {
hashCode = key;
} else {
hashCode = key[this.hashcodeField()];
}
if (hashCode) {
var prev = this.backing_hash[hashCode];
this.backing_hash[hashCode] = undefined;
if (prev !== undefined)
success = true;
}
}
return success;
}
}
/*
=====================================================================
usage
=====================================================================
*/
// creation
var my_map = new HashMap();
// insertion
var a_key = {};
var a_value = {struct: "structA"};
var b_key = {};
var b_value = {struct: "structB"};
var c_key = {};
var c_value = {struct: "structC"};
my_map.put(a_key, a_value);
my_map.put(b_key, b_value);
var prev_b = my_map.put(b_key, c_value);
// retrieval
if(my_map.get(a_key) !== a_value){
throw("fail1")
}
if(my_map.get(b_key) !== c_value){
throw("fail2")
}
if(prev_b !== b_value){
throw("fail3")
}
// deletion
var a_existed = my_map.del(a_key);
var c_existed = my_map.del(c_key);
var a2_existed = my_map.del(a_key);
if(a_existed !== true){
throw("fail4")
}
if(c_existed !== false){
throw("fail5")
}
if(a2_existed !== false){
throw("fail6")
}
// primitive types keys
var d_value = {struct: "structD"};
my_map.put(1, d_value);
if (my_map.get(1) !== d_value) {
throw("fail7")
} |
The keys and values can be arbitrary javascript objects.
There is no requirements on objects used as keys or values.
The mechanism is trivial. For every key there is generated unique id (per HashMap instance).
That id is injected to the key object under high unlikely to collide field name
That id is then used to keying in the underlying baking standard javascript association object.
Notes:
1. This HashMap implementation is not thread safe.
OK I know javascript is not multithreaded but it can have concurrent activities (e.g. setTimeout)
This is enough to have race conditions.
2. The mentioned high unlikely to collide name is not a problem as log as there is no
massively concurrent activities.
Roadmap:
1. Make the HashMap implementation thread safe by applying The Wallace Variation of Lamport’s bakery algorithm.
http://www.polyglotinc.com/AJAXscratch/Mutex/mutualExclusion.html
Bon Appétit,
Daniel Kwiecinski
Recently I had a need to use routing definition of one RoR from the other one (don’t ask why it’s irrelevant to this post
)
As you may know Rails routing mappings are stored in global variable ActionController::Routing::Routes. So together with Craig McMillan I’ve hacked really evil piece of code
but it does the job!
So here it goes:
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
| # evil Ruby dynamic variables
class DynamicValue
def initialize(val)
@default_value = val
end
def method_missing(name, *args, &proc)
if tv=Thread.current['DynamicValue']
tv.send( name, *args, &proc)
else
@default_value.send( name, *args, &proc)
end
end
def with_dynamic_value(value)
tmp = Thread.current['DynamicValue']
begin
Thread.current['DynamicValue'] = value
yield
ensure
Thread.current['DynamicValue'] = tmp
end
end
def to_s
"dynamic value"
end
def inspect
to_s
end
end |
One can use it for example like this:
# let's deal with fresh empty RouteSet object
ActionController::Routing::Routes.with_dynamic_value( ActionController::Routing::RouteSet.new ) do
# let's load other RoR routes to it
load File.join(Sonar::SONAR_ROOT, 'other_ror', 'config', 'routes.rb')
# now we can use the other RoR routing definition to generate email tamplate used from the other RoR
email = NewItemsMessage::create_new_message(person)
end
Only thread invoking with_dynamic_value will experience the variable reassignment. For other threads it will be transparent. Once the thread exit the block, again it will see the value in the variable as it was before the trick.
In order to enable that evil you have to invoke once and only once (placing it at the end of config/environment.rb should be fine) the following line:
ActionController::Routing.const_set("Routes", DynamicValue.new(ActionController::Routing::Routes))
Or any other variable substitution. Doing it once is important because applying more than one proxy will discard the original value of the variable.
Enjoy more LISP’y Ruby
This is more verbose answer to @bubbafat twitt-question. It started lkie this:
- @bubbafat: Functions used by spawn to start a process must be exported. Why doesn’t erl compiler error when this is missed? #erlang
- @danielllo: @bubbafat ‘cos it is possible to define and load new modules later on during runtime in #erlang
- @bubbafat: @danielllo Thx. Do you mean redefining the module at runtime or that the func might resolve in a different module loaded later? #erlang
- @danielllo: You have many ways of referencing #erlang module:function not known at compile time.
-
- you can load the precompiled module at later time from a path not being provided to compiler.
- you can use M:F(Args) function invocation in #erlang, any of M, F, Args being variables dynamically referencing module, function and argument list.
- you can construct erlang AST tree programmaticaly, compile it at runtime and load the resulting beam.
- you can acheive the p.3 result using a helper tools such as LFE, Smerl or “Dynamic” module generation with compile-time macros
- … and I’m sure there is more
Recently I was looking for an example on how to do redirect in webmachine. Unfortunately I haven’t found one. So I started figuring it out by myself. After try and error using brilliant wmtrace_resource It turned out to be trivial ;). Here is the example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| %% @doc Example of redirect webmachine_resource.
-module(redirect_resource).
-export([init/1, resource_exists/2, moved_temporarily/2, previously_existed/2]).
-include_lib("webmachine/include/webmachine.hrl").
init([]) -> {ok, undefined}.
moved_temporarily(ReqData, Context) ->
Site = wrq:path_info(site, ReqData),
Location = base64:decode(Site),
{{true, Location}, ReqData, Context}.
previously_existed(ReqData, Context) -> {true, ReqData, Context}.
resource_exists(ReqData, Context) -> {false, ReqData, Context}. |
The resource is mapped in my dispatch.conf as
{["redirect", site], redirect_resource, []}.
You can do a request like http://host.com/redirect/aHR0cDovL2xhbWJkZXIuY29t
The redirect_resource will interpret the last token in the path as base64 encoded location to redirect to.