Last active
August 29, 2015 13:57
-
-
Save jkrems/9362717 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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