Skip to content

Instantly share code, notes, and snippets.

@jkrems
Last active August 29, 2015 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jkrems/9362717 to your computer and use it in GitHub Desktop.
Save jkrems/9362717 to your computer and use it in GitHub Desktop.
// 1. Variable declaration
def myValue = 'value, immutable';
def myObjectValue = { a: 10 };
myObjectValue.b = 20; // TypeError
myObjectValue.a = 12; // TypeError
def myArrayValue = [ 10, 20 ];
myArrayValue.slice(1); // is okay, slice is pure
myArrayValue.pop(); // TypeError
myArrayValue.splice(); // TypeError
mutable myVariable = 'variable, mutable';
def myObjectVariable = { a: 10 };
myObjectVariable.a = 20; // that's fine
myObjectVariable.b = 12; // also fine
// 2. Function declaration
def mul = (x, y) -> x * y;
[ 1, 2 ].map( x => x * x );
[ "foo", "bar" ].map(.substr(1)); // .substr(1) = function(v) { return v.substr(1); }
// 3. Explicit typing
def a : string = 'explicitly typed';
// Various levels of explicitness for functions
def fn1 : string = (name) -> 'Hello, ' + name;
def fn1 = (name) : string -> 'Hello, ' + name;
def fn1 = (name : string) -> 'Hello, ' + name;
def fn1 : string = (name : string) -> 'Hello, ' + name;
def fn1 : string -> string = (name : string) -> 'Hello, ' + name;
def fn1 : (string) -> string = (name : string) -> 'Hello, ' + name;
def fn1 : (string) -> string = (name : string) -> { 'Hello, ' + name; };
def fn1 = function(name : string) : string { 'Hello, ' + name; };
// function parameter typing
mutable extractTwo<T> : (error, data : T, ...) -> Promise<T>;
mutable readFile<T> : (filename, encoding = 'utf8', callback? : (error : Error, data : Buffer) -> T) -> Promise<Buffer>;
// with typedef
typedef BufferCallback<T> (error : Error, data: Buffer) -> T;
mutable readFile<T> : (filename, encoding = 'utf8', callback? : BufferCallback<T>) -> Promise<Buffer>;
// `callback?` can be written as Option<callback> = None
mutable readFile<T> : (filename, encoding = 'utf8', callback : Option<BufferCallback<T>> = None) -> Promise<Buffer>;
// 4. To prevent auto-return, explicit return type `void` has to be used
def g : void = (a) -> {
console.log('no auto-return');
};
// 5. Assigning `null` or `undefined` is only allowed for Option type
mutable numberOption : Option<number> = 2;
numberOption = null; // None
mutable normalNumber : number = 2;
// normalNumber = null; // not allowed
// 6. match expression, marked by passed in value
match(x) {
case Some(n): console.log("Has some!", n); // matches non-null/non-undefined
case None: console.log("Is empty."); // matches null and undefined
};
// 7. match function, b/c match used without argument
def getLength = match {
case (list : Array<T>):
list.length;
case (str : string):
str.length;
case (n : number):
parseInt(n.toExponential().match(/(-?[\d]+)$/), 10);
};
console.log(getLength([ 1, 2 ])); // 2
console.log(getLength('foo')); // 3
console.log(getLength(4335)); // 4
// 8. sugar for "case classes" & typedef
class Rectangle(width : number, height : number);
/**
* const Rectangle = function(width, height) {
* this.width = width; this.height = height;
* };
*
*/
class Circle(radius : number) {
// constructor is not allowed because implicitly defined
toString() : string {
`Circle(r = ${this.radius})`;
}
get diameter() {
return 2 * this.radius;
}
scaled(factor : number) : Circle {
new Circle(this.radius * factor);
}
}
typedef Shape { Rectangle, Circle };
typedef EscapedHtmlString { string }; // typedef, just for type checking
typedef EscapedHtmlString string; // shorter version if it's only one type
typedef BufferCallback<T> (error : Error, data: Buffer) -> T;
def height = match {
// same as for harmony arrow function, parenthesis
// around single parameter is optional
case Rectangle({ height }): height;
case Circle({ radius }): 2 * radius;
};
console.log(height(Rectangle(100, 200))); // 200
console.log(height(Circle(150))); // 300
console.log(height(new Circle(150))); // 300
// 9. More realistic function match use case
def fetch = match {
case (uri : string, opts, cb):
fetch(extend({uri}, opts), cb);
case (uri : string, cb):
fetch({uri}, cb);
case (opts, cb):
// logic!
};
// 10. `object` sugar for Object.create
object myObj extends ProtoObject {
propA: {
value: 'foo'
}
}; // const myObj = Object.create(ProtoObject, { propA: { value: 'foo' } });
object myObj instanceof SomeClass {
propA: { value: 'foo' }
}; // const myObj = Object.create(SomeClass.prototype, { propA: ... }); SomeClass.call(myObj);
// 11. extended mutability
def myObj = { x: 2, op: -> this.x = 10, op2: -> this.x };
myObj.op2(); // is fine since `op2` is pure
myObj.op(); // won't compile since `op` is not pure
mutable myMutableObj = { x: 2, op: -> this.x = 10, op2: -> this.x };
myMutableObj.op(); // not a problem
myMutableObj = myObj; // won't compile because it would make myObj mutable
myMutableObj = _.clone(myObj); // is fine, only a copy is made mutable
// 12. types with assertions
typedef NonEmptyString { string | value.length > 0 };
typedef Truthy { any | !!value };
typedef LongLength { string, Array | value.length > 0 };
// const LongLength = { isLongLength: function(value) { verify } };
0 instanceof Truthy; // false
"" instanceof NonEmptyString; // false
"a" instanceof NonEmptyString; // true
"a" instanceof LongLength; // true
[] instanceof LongLength; // true
// 13. interfaces
typedef Chunk { string, Buffer };
interface WriteableStream {
write(chunk : Chunk) : WriteableStream
end(chunk? : Chunk) : WriteableStream
}
// const WriteableStream = {
// isWriteableStream: function(obj) { verify interface }
// };
object someStream {
write(chunk: Chunk) { this }
end(chunk?: Chunk) { this }
} instanceof WriteableStream; // true because it matches the interface
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment