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