Adventures in New Tech for an Old Coder
I am exploring two new languages and a Distributed VCS. Ruby and Node.js. Node.js is intrinsically event driven and Ruby has EventMachine. Git is a VCS born of Linus Torvalds mind.
Saturday, August 4, 2012
Saturday, June 23, 2012
IEEE 754 may not be such a kluge I thought it was
function log2(v) { return Math.log(v)/Math.LN2 }
log2(Number.MAX_VALUE) //=> 1024
The Log base 2 of the Maximum double floating point number is 1024. There is something elegant about that. My respect for IEEE 754 just went up.
Friday, September 23, 2011
Again: exports and module.exports in JavaScript Modules
If you
require() a module there are a couple simple rules:- you don't need to put the '.js' on the end of the file.
- if you
require('./my_module')the file must be in
- ./my_module.js or
- ./my_module/index.js
- if you
require('my_module')the file must be in
- ./node_modules/my_module.js or
- ./node_modules/my_module/index.js or
- or a node_modules directory toward root (.. or ../.. or ../../.. till /node_modules)
As for the module file itself, you must set the object to be returned from the
require() call. This is the part that flummoxed me.It is simple, in your module there is a module variable automagically. That module variable points to an object that is pre-populated with many properties. Just do a
console.dir(module) in your empty module file to see it all.The object that gets returned from the
require() call is pre-allocated in the module.exports property. There is also a variable called exports that contains the very same object that is in module.exports. If you assign a new object to the exports variable, eg exports = {};, that new object will NOT be exported as it is not the same object that is in module.exports. Think of it as if there is a invisible exports = module.exports = {}; line at the beginning of your module. The exports variable is only there for your convenience and only the object pointed at by module.exports matters.This is simple and I found no one who said it straight out. There was crap about exports being an "alias" for module.exports and other balderdash. If you want to create your own elaborate exported object just do this:
exports = module.exports = {
... my big-ass exported object ...
};
Thursday, September 22, 2011
CommonJS exports spec ambiguity
- In a module, there is a free variable called "exports", that is an object that the module may add its API to as it executes.
- modules must use the "exports" object as the only means of exporting.
There is no mention of "module" or "module.exports".
I've also realized I am a blithering idiot. I put
console.dir(module); in an empty module and I saw that it was populated with a great many things. Most pertinently, module has a property named exports already initialized to an empty object. If you add something to module.exports like module.exports.foo = 'bar'; then console.dir(exports); will output { foo : 'bar' }. It is sad how much my coding skills have atrophied the last few years. I used to be rather sharp ... oh well.
Tuesday, September 20, 2011
Nodejs: module.exports and exports
Requiring modules is simple
var m = require('./my_module');
m.myFunc(foo, bar);
The file needs to be "./my_module.js", with the following exports line:var myFunc = function () { ... };
module.exports.myFunc = myFunc;
The Why is the hard part. You can't do exports = {}, but you can do module.exports = {}. Turns out module is the "global" namespace in an require() file. exports is some sort of "alias" for module.exports (I haven't figured that out). What this means is that exports.myFunc = myFunc; is OK, but exports = {myFunc: myFunc} is NOT OK, BUT module.exports = {myFunc: myFunc} is OK. Basically, I've decided not to use this pseudo-whatchamacalit "alias" type thing exports. I'll just use module.exports. Additionally, it is probably best to use the form:module.exports.myFunc = function () {
...
};
for all exported functions inside ./my_module.js
Monday, August 22, 2011
Tuesday, August 16, 2011
Syncronous coding style with EventMachine and Fibers
require 'fiber'
require 'eventmachine'
class AsyncIO < EM::Connection
include EM::P::LineText2
def initialize df
@df = df
end
def receive_line line
@df.succeed line
end
end
def get_line
f = Fiber.current
df = EM::DefaultDeferrable.new
df.callback { |line| f.resume(line) }
EM.connect '127.0.0.1', 3000, AsyncIO, df
return Fiber.yield
end
EM.run {
Fiber.new {
line = get_line
puts line
EM.stop
}.resume
}The truth is you should look at EM::Sychrony. Ilya Grigorik explains in he own Blog, how Fibers can help you write synchronous code while keeping the goodness of AsyncIO (ala EventMachine).
I don't find event driven code to be "callback hell" like Ilya Grigorik does. I find evented code easier to read than synchronous code sometimes. In Synchronous code you have to check every time if it failed and why. That is
if (rc < 0)with
switch (errno) case EINTR:code after every network call. In event driven code that stuff is dealt with in the event-loop and you just have to define the error callback once.
Ah well just use Node.js . If JavaScript event driven programming is "to hard" for your delicate sensibilities then explain to me how Millions of Web-monkeys pull it off everyday in the browser.