Don't believe me.
Not even when I'm (mis)quoting clever people.
Don't believe them either.
Try things for yourself.
Particularly those that seem revolting at first.
Would you seriously trust a bridge, let alone an airplane, built the way we build software?
That's a worthy goal, but it is far ahead.
There are no shortcuts.
Engineering comes from ingenuity.
I think that it's extraordinarily important that we in computer science keep fun in computing. [...] We began to feel as if we really were responsible for the successful, error-free perfect use of these machines. I don't think we are. I think we're responsible for stretching them, setting them off in new directions, and keeping fun in the house. [...]
The ones that are about programming often cause more problems than they solve.
The ones that add value are about communication.
List of all proven methods to avoid bugs in code:
The codebase becomes a terrible mess all by itself.
No need to accelarate the process.
Leave yourself the room to maneuvre.
It seems that perfection is attained not when there is nothing more to add, but when there is nothing more to remove.
Problem: You need to cut and pinch
Problem: You need to cut and pinch
There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.
There is evidence to suggest it works.
The single responsibility principle states that every class should have a single responsibility, and that responsibility should be entirely encapsulated by the class.
In the beginner's mind there are many possibilities, in the expert's mind there are few.
Does Haxe deliver on the promise Java failed to keep?
(That's a serious question, but for now let's go with:)
Of course it does!!!
What's not in Haxe is as important as what is.
A continuous work in progess.
Many small, well documented packages.
Composability!!! Composability!!! Composability!!!
Example: tink.core.Signal
has a map
and a filter
method. Let's make it pausable!
function pausable<T>(s:Signal<T>) {
var paused = false;
return {
signal: s.filter(function (_) return !paused),
isPaused: function () return paused,
setPaused: function (param) paused = param,
}
}
typedef Button {
var clicked(default, null):Signal<MouseEvent>
}
var up:Button = ...,
down:Button = ...;
var delta = up.clicked.map(function (_) return -1).join(
down.clicked.map(function (_) return 1)
);
$type(delta);//Signal<Int>
Use in any class with implements tink.Lang
.
Extended syntax is applied to the class and all subclasses.
class Point implements tink.Lang {
public var x = (.0);
public var y = (.0);
@:calculated var length = Math.sqrt(x * x + y * y);
}
Do you hate it to have an expression end with })]})
?
Mysql.connect() => {
database : 'test',
user : 'user',
password : 'password',
}
[] => 4;
[x] => 2 * x;
[x, y] => x + y;
x => 2 * x;
@do body;
@do(x, y) trace(x + y);
@f value;
@f(x, y) (x + y);
function () return 4;
function (x) return 2 * x;
function (x, y) return x + y;
function (x) return 2 * x;
function () body;
function (x, y) trace(x + y);
function () return value;
function (x, y) return x + y;
switch _ {}
switch [_, _] {}
@do switch _ {}
@f switch _ {}
function (x) return switch x {}
function (x, y) return switch [x, y] {}
function (x) switch x {}
function (x) return switch x {}
myButton.clicked.handle() => @do {
trace('clicked!!!');
}
http.load(someUrl).handle() => @do switch _ {
case Success(data): trace('loaded $data');
case Failure(error): trace('ERROR: $error!');
}
for (i += .5 in 0...100) {}
for (i -= .5 in 100...0) {}
for ([b in bananas, m in monkeys]) m.eat(b);
for ([b in bananas, m in monkeys || monkey[0]]) m.eat(b);
for (key => value in map) {}
for ([m in monkeys, i++]) {}
@:tink_for({
var i = 0, a, l;
{
a = untyped __call__('array_values', @:privateAccess this.h);
l = untyped __call__('count', a);
}
}, i < l, a[i++])
function iterator():Iterator<T>;
Interfaces can have implementation
interface Enumerable<T> implements tink.Lang {
@:calc var length = fold(0, function (count, _) return count + 1);
function fold<A>(init:A, calc:A->T->A):A {
forEach(function (v) init = calc(init, v));
return init;
}
function forEach(f:T->Void):Void
for (v in this) f(v);
function map<A>(f:T->A):Array<A> {
var ret = [];
forEach(ret.push);
return ret;
}
}
Partial implementation can have dependencies
interface Enumerable<T> implements tink.Lang {
/* ... */
@:usedOnlyBy(iterator)
var elements:Array<T> = [];
@:usedOnlyBy(forEach)
public function iterator():Iterator<T> {
return elements.iterator();
}
}
class Stack implements tink.Lang {
@:forward(push, pop, iterator, length) var elements:Array;
public function new() {
this.elements = [];
}
}
function connect<T>(
args = {
host: 'localhost',
port: 3306,
'database': 'test',
username: (_ : String),
password: (_ : String)
}
) {
return Mysql.connect(args);
}
Automatically connects. Creates missing tables and adds missing columns. Initializes SPOD.
Usage: -lib tinx_autospod tinx.AutoSpod.use()
(See #3037)
Configuration through dbconfig.uri
in working directory
mysql://user:password@host:port/dbname
sqlite:path/to/file.db
alias:path/to/directory
Largely haxe.Template
compatible compile time template language with rich syntax,
including switch
, while
, for
, var
, function
.
Templates become true Haxe classes on the fly, that can implement interfaces and extend classes.
Usage: -lib tinx_autospod tinx.AutoSpod.use()
No support for import
and using
(see #2868).
//Example.tpl
::static inline var TITLE = 'Awesome blog'::
::static function header(?title = TITLE)::
<!DOCTYPE html><html><head><title>::title</title></head>
<body>
::end::
::static function index(posts:Array<Post>)::
::header()::
::for p in posts:: ::excerpt(p):: ::end::
::footer()::
::end::
::static function excerpt(p:Post)::
::p.excerpt()::
<a href="/post/::p.id::">Read more</a>
::end::
::static function doDefault()
Sys.print(index(Post.manager.all()))
::
::static function main()
Dispatch.run(Web.getURI(), Web.getParams(), Example)
::
abstract Html {
public function new(s:String):Void;
@:from static public function escape(s:String):Html;
@:from static function ofMultiple(parts:Array<Html>):Html;
@:from static public function of<A>(a:A):Html;
}