Skip to content

Instantly share code, notes, and snippets.

@komuw
Last active June 25, 2020 21:45
Show Gist options
  • Select an option

  • Save komuw/930d2663b8d0d56ab148f18762166f57 to your computer and use it in GitHub Desktop.

Select an option

Save komuw/930d2663b8d0d56ab148f18762166f57 to your computer and use it in GitHub Desktop.
my Dartlang notes
// install
// ref:: 1. https://www.dartlang.org/tools/sdk#install
// untill dart 2 stable is released
var install = """
sudo sh -c 'curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -'
sudo sh -c 'curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_unstable.list > /etc/apt/sources.list.d/dart_unstable.list'
sudo apt -y update
sudo apt -y install dart
"""
// u also need to add dart's bin dir to path. it isuallay at; /usr/lib/dart/bin
// this will enable tools like pub, dartdevc etc to work
var installMac = """
brew tap dart-lang/dart
brew install dart --head // to install dev channel
brew update
brew upgrade dart
"""
/*
1. Profile/Debug:
To debug, run your program as;
dart --observe=9897/localhost ~/Downloads/cool.dart
//https://dart-lang.github.io/observatory
You can insert a debugger by;
import 'dart:developer';
debugger();
2. Normal running
dart cool.dart
dart --enable-experiment=non-nullable cool.dart
3. Generate js
dartdevc -o output.js cool.dart
4. Generate js for prod
dart2js -m --out=output-prod.js cool.dart // -m is minification
5. static analysis
dartanalyzer --no-declaration-casts --no-implicit-casts --no-implicit-dynamic --fatal-warnings cool.dart
6. fmt
dartfmt --overwrite --profile --follow-links --line-length 100 .
7. snapshot
dart --snapshot=example.jit --snapshot-kind=app-jit example/example.dart
dart example.jit // to run it
// see:: https://github.com/dart-lang/sdk/wiki/Snapshots
8. install a package as executable
pub global activate <packageName>
// if you get weird errors;
rm -rf ~/.pub-cache/
9. create and serve a simple web app
pub global activate stagehand &&
stagehand web-simple && \
pub get
pub run build_runner serve -v --output=web:output --no-release # to serve. an alternative is;
pub run build_runner build -v --output=web:output --no-release && \
cd output && \
python -m SimpleHTTPServer 8000
# u need a server because of Chrome security constraints
Also see;
https://dev.to/graphicbeacon/build-a-basic-chat-application-in-dart-2-part-1-4ekj
10. Futures - Isolates - Event Loop - async
https://www.didierboelens.com/2019/01/futures---isolates---event-loop/
*/
//I. Variables
// Uninitialized variables have an initial value of null
int lineCount;
assert(lineCount == null);
var name = 'Bob'; //type infered
String name = 'Bob'; //typed
// final vars can only be set once
// const are compile time constants
final name = 'Bob'; //type infered
// name = 'Alice'; // Uncommenting this causes an error
final String nickname = 'Bobby'; //typed
const double atm = 1.01325;
var foo = const []; //foo can be changed later.
final bar = const []; //cant be changed, immutable.
const baz = const []; //cant be changed, immutable.
//II. Built in types
int x = 1;
double y = 1.1;
// A Dart string is a sequence of UTF-16 code units
var s1 = "Single or Double quotes work.";
var s2 = """This is also a
multi-line string.""";
var s3 = r"In a raw string, even \n isn't special.";
// ref:: https://api.dartlang.org/dev/dart-core/String-class.html
// Only two objects have type bool:
// the boolean literals true and false,
// Dart treats all values other than true as false
var list = [1, 2, 3];
var constantList = const [1, 2, 3]; // immutable
var gifts = {"second": "turtledoves",}; // map
final constantMap = const {2: 'helium', 10: 'neon'}; // immutable
// In Dart, Runes are the UTF-32 code points of a string.
#radix // symbol
//III. Functions
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
isNoble(atomicNumber) {
return _nobleGases[atomicNumber] != null;
} // can also wok without types
// ALso check out
// 1. the => fat arrow syntax for funcs
// 2. optional params
// 3. default params
// ref:: https://www.dartlang.org/guides/language/language-tour#optional-parameters
// I'm skipping those since Go doesn't have 'em & I dont think I need 'em now.
// Every app must have a top-level main() function;entrypoint.
// main() returns void and has an optional List<String> parameter for arguments.
void main(List<String> arguments) {
print(arguments);
assert(arguments.length == 2);
assert(int.parse(arguments[0]) == 1);
assert(arguments[1] == 'test');
}
// example of main() func for a cli app that takes arguments
// u can pass a func to another as arg and you can also asssign it to a var
// A closure is a function object that has access to variables in its lexical scope,
// even when the function is used outside of its original scope.
makeAdder(num addBy) {
// makeAdder returns a function that adds [addBy] to the funcs args
// the returned func will have access to both addBy and z even when out of scope
var z = 10;
return (int i) { // anonymous/unamed func
return addBy + i + z;
};
}
void main() {
// Create a function that adds 2.
var add2 = makeAdder(2);
print(add2(3)); // prints 15 ie 3+2+10
}
//IV. Operators
// ref:: https://www.dartlang.org/guides/language/language-tour#operators
// To test whether two objects x and y represent the same thing,
// use the == operator
// In the rare case where you need to know whether
// two objects are the exact same object, use the identical() func
print(identical(5,5)); // prints true
// most operators such as == are methods and u can ovveride them
// NB: if you ovvereide == operator u should also ovveride the hashCode property.
// ref:: https://www.dartlang.org/guides/language/language-tour#overridable-operators
class Vector {
final int x, y;
const Vector(this.x, this.y);
// Overrides + ie (a + b). ie define a + method to add two vectors.
Vector operator +(Vector v) {
return new Vector(x + v.x, y + v.y);
}
}
void main() {
final v = new Vector(1, 2);
final w = new Vector(3, 4);
var z = v + w;
print(z.x); // prints 4
print(z.y); // prints 6
}
a = value; // Assign value to a
b ??= value; // Assign value to b if b is null; otherwise, b stays the same
int a = 4;
int b;
a ??= 8;
b ??= 7;
print(a); // 4
print(b); // 7
// If condition is true, evaluates expr1 (and returns its value);
// otherwise, evaluates expr2 and returns its value.
condition ? expr1 : expr2
// If expr1 is non-null, returns its value;
// otherwise, evaluates expr2 and returns its value.
expr1 ?? expr2
// cascade notation
// allow you to make a sequence of operations on the same object.
// In addition to FUNCTION CALLS, you can also ACCESS FIELDS on that same object.
var sb = ' ALPHABET ';
var x = sb.toLowerCase()
..trim()
..toString();
print(x); // alphabet
// ref:: https://www.dartlang.org/guides/language/language-tour#cascade-notation-
//I. if
if (isRaining()) {
you.bringRainCoat();
} else if (isSnowing()) {
you.wearJacket();
} else {
car.putTopDown();
}
// NB: Dart treats all values other than true as false
//II. for
var message = new StringBuffer('Dart is fun');
for (var i = 0; i < 5; i++) {
message.write('!');
}
// Closures inside of Dart’s for loops capture the value of the index,
// avoiding a common pitfall found in JavaScript.
void main() {
var callbacks = [];
for (var i = 0; i < 5; i++) {
callbacks.add(() {
return i;
});
}
for (var x in callbacks) {
print(x()); // prints 0,1,2,3,4
}
}
// Dart also has the following loops
// while
// do-while
// break
// continue
//III. switch
// they compare integer, string, or compile-time constants using ==
// there are some other conditions
// switch work well with Enums
// switch are intended for limited circumstances, such as in interpreters or scanners.
// ref:: https://www.dartlang.org/guides/language/language-tour#switch-and-case
var command = 'OPEN';
switch (command) {
case 'CLOSED':
executeClosed();
break; // break has to be there else compile error
case 'PENDING':
executePending();
break;
case 'OPEN':
executeOpen();
break;
default:
executeUnknown();
}
//IV. Exceptions
// dart has Exception & Error types, plus numerous predefined subtypes. u can also define ua own
throw new FormatException('Expected at least 1 section');
// u can catch specific or general exceptions
try {
breedMoreLlamas();
} on OutOfLlamasException {
// A specific exception
buyMoreLlamas();
} on Exception catch (e) { // Anything else that is type exception
print('Unknown exception: $e');
} catch (e, s) { // No specified type, catch all
print('Exception details:\n $e');
print('Stack trace:\n $s');
}finally { // code that runs if exception is thrown or not
cleanLlamaStalls();
}
//I. Objects have members consisting of;
// - functions and
// - data (ie methods and instance variables, respectively).
class Point {
num x, y; // instance vars, intially null
num z = 0; //intilly 0
Point(this.x, this.y); // constructor. it is also setting x & y
Point.origin() { //named constructor
x = 0;
y = 0;
}
}
void main() {
var point = new Point(4, 7);
print(point.x);
}
// constructors are NOT inherited
// read about named constructors
// ref:: https://www.dartlang.org/guides/language/language-tour#named-constructors
// during inheritance, to invoke a superclass's constructor
// specify the superclass constructor after a colon (:), just before the constructor body (if any)
class Person {
String firstName;
Person.cool(int data) { //named constructor
print('in Person');
}
}
class Employee extends Person {
Employee.cool(int data) : super.cool(data) {
print('in Employee');
}
}
void main() {
new Employee.cool(34);
}
// the order of execution is as follows:
// 1. initializer list
// 2. superclass’s no-arg constructor
// 3. main class’s no-arg constructor
//II. initializer list
// u can initialize instance variables before the constructor body runs.
class Point {
final num x;
final num y;
final num sum;
Point(x, y) : x = x, y = y, sum = x + y; // The right-hand side of an initializer does not have access to this keyword
}
main() {
var p = new Point(2, 3);
print(p.sum); // prints 5
}
// If your class produces objects that never change,
// you can make these objects compile-time constants.
// look at factory constructors
// also look at fact that u cn define custom getters and setters
//III. instance methods
class Point {
num x, y;
Point(this.x, this.y);
num sub() { // instance mthod; can access instance variables and this keyword
return x - this.y;
}
}
main() {
var p = new Point(2, 3);
print(p.sub());
}
// abstract classes
// they cant be instantiated.
// they r useful for defining interfaces
abstract class Doer {
// Define instance variables and methods...
void doSomething(); // Define an abstract method.
}
class EffectiveDoer extends Doer {
void doSomething() {
// Provide an implementation, so the method is not abstract here...
}
}
// as seen before; use extends to create child class and super to refer to parent
// u can use the @override annotation to indicate that you are intentionally overriding a member
class Television {
void turnOn() {
print("tv");
}
void cool() {
print("cool");
}
}
class SmartTV extends Television {
void turnOn() {
super.turnOn();
print("smartTv");
}
}
main() {
var stv = new SmartTV();
stv.turnOn(); // prints tv , smrtTv
stv.cool(); // prints cool
}
//IV. class/static vars and methods
// we've been looking at instance vars and methods.
// now we look at class ones; they do not have access to this keyword
// they are good for class wide state & constants
class Point {
static const int x = 16; // class var
static int y = 4;
static num div() { // class method
return x / y;
}
}
void main() {
print(Point.div()); // class vars/methods are called on the class not class instance
print(Point.x);
}
//V. Callable classes
// if u implement the call() method, ua classes can be called like a function.
class Yolo {
int x = 4;
call() {
return x;
}
}
main() {
var yol = new Yolo();
print(yol());
}
//VI. Enums
// they are special type of class used to represent a fixed number of constant values.
enum Color { // cant be declared inside main func
red, green, blue
}
main() {
assert(Color.green.index == 1); // each value has an index
List<Color> cList = Color.values; // can convert 'em to a list using .values property
print(cList);
var x = Color.blue;
switch (x) {
case Color.red:
print('Red as roses!');
break;
default: // Without this, you see a WARNING.
print(x); // 'Color.blue'
}
}
// well specified generics result in better generated code
// they also reduce code duplication
// generic types are reified(they carry their type information around at runtime) unlike java where they have erasure
// if u were making a k-v store
abstract class KV {
String getKey(String key);
void setKey(String key, String value);
}
// however, u would like your kv db to be able to store anything not just strings
abstract class KV<T> {
T getKey(String key);
void setKey(String key, T value);
}
// list and maps can also be parametized
var names = <String>['Seth', 'Kathy', 'Lars'];
var matatus = <int, String>{118: 'kabete', 45: 'githurai'};
// or when using construtors
var names = new List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
var x = new Map<int, String>();
x[119] = "mwimuto";
// read on using generic methods
// ref:: https://www.dartlang.org/guides/language/language-tour#using-generic-methods
// ref:: https://github.com/dart-lang/sdk/blob/master/pkg/dev_compiler/doc/GENERIC_METHODS.md
// Every Dart app is a library, even if it doesn’t use a library directive.
// identifiers that start with an underscore (_) are visible only inside the library.
import 'dart:html'; // built-in libs have a dart identifier
import 'package:test/test.dart'; // for others, use package as identifier
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2; // aliasing libs
import 'package:lib1/lib1.dart' show foo; // import only foo
import 'package:lib2/lib2.dart' hide foo; // import everything from lib except foo
// rea about implementing libs
// ref:: https://www.dartlang.org/guides/language/language-tour#implementing-libraries
// Dart is full of async funcs that return Future or Stream objects.
// I. FUTURES
// when you need the result of a completed Future, you have two options:
// 1. Use async and await.
// 2. Use the Future API.
// u should prefer using async/await over futures api: https://www.dartlang.org/guides/libraries/library-tour#future
//1. async/await
Future lookUpVersion() async {
return '1.0.0';
}
// or if you want to also use types
Future<String> lookUpVersion() async {
return '1.0.0';
}
Future<void> main() async {
var ver = await lookUpVersion(); // u cant use await in a synchronous func; it's a compile error
print(ver); // prints 1.0.0
}
// u can use normal try-catch in async/await
// 2. future api
// u should prefer to use async/await instead of this. having said that;
// u can use .then() to schedule code that runs when the future completes
import 'dart:io';
void main() {
HttpClient client = new HttpClient();
client
.getUrl(Uri.parse("http://google.com"))
.then((HttpClientRequest request) {
// Optionally set up headers...
// Optionally write to the request object...
// Then call close. close completes with an HttpClientRequest object.
return request.close();
}).then((HttpClientResponse response) {
print(response.headers);
// Process the response.
// read/drain respone to avoid resource leaks
response.drain();
}).catchError((e, s) {
print(e);
print(s);
});
}
// A getUrl request is a two-step process, triggered by two Futures.
// When the first future completes with a HttpClientRequest, the underlying network connection has been established,
// but no data has been sent, the HTTP headers and body can be set on the request.
// Either the first write to the request object or a call to close sends the request to the server.
// When the HTTP response is received from the server,
// the second future, completes with an HttpClientResponse object
// If a body is present, it must be read. Otherwise, it leads to resource leaks.
// The above code is equivalent to;
import 'dart:io';
import 'dart:async';
Future<HttpClientResponse> sendRequest(HttpClientRequest request) {
return request.close();
}
Future receiveRes(HttpClientResponse response) {
print(response.headers);
return response.drain(); // avoid leaks
}
void main() {
HttpClient client = new HttpClient();
var f = client.getUrl(Uri.parse("http://google.com"));
var x = f.then(sendRequest);
var eee = x.then(receiveRes);
eee.catchError((e, s) {
print(e);
print(s);
});
}
// Which is equivalent to;
import 'dart:io';
import 'dart:async';
Future<void> main() async {
HttpClient client = new HttpClient();
try {
var f = await client.getUrl(Uri.parse("http://google.com"));
var req = await f.close();
var headers = req.headers;
print(headers);
await req.drain();
} catch (e, s) {
print(e);
print(s);
}
}
// notice the async/await version is simpler & easier to reason about
// read about how to wait for multiple futures using .wait method
// ref:: https://www.dartlang.org/guides/libraries/library-tour#waiting-for-multiple-futures
// II. STREAMS
// when u need to get values from a Stream, you have two options:
// 1. Use async and an asynchronous for loop (await for).
// 2. Use the Stream API.
// u should prefer using async/await-for over Stream api: https://www.dartlang.org/guides/libraries/library-tour#stream
// Before using `await for`, make sure that it makes the code clearer and that you really do want to wait for all of the stream’s results.
// For example, you usually should not use await for for DOM event listeners, because the DOM sends endless streams of events.
// If you use await for to register two DOM event listeners in a row, then the second kind of event is never handled.
// 1. async/await-for
Future main() async {
await for (var request in requestServer) {
handleRequest(request);
}
}
// 2. Stream api
// read about stream api
// ref:: https://www.dartlang.org/guides/libraries/library-tour#stream
// To get each value as it arrives, either use await for or subscribe to the stream using the listen() method:
// Example: Find a button by ID and add an event handler.
querySelector('#submitInfo').onClick.listen((e) {
// When the button is clicked, it runs this code.
submitData();
});
// III. Generators
// when you need to lazily produce a sequence of values, consider using a generator function
// Dart has built-in support for two kinds of generator functions:
// 1. Synchronous generator: Returns an Iterable object. (sync*)
// 2. Asynchronous generator: Returns a Stream object. (async*)
// 1. sync*
Iterable<int> iterTo(int n) sync* {
int k = 0;
while (k < n) yield k++;
}
void main() {
var x = iterTo(7);
x.forEach((item) {
print(item); // prints 1-6
});
}
// 2. async*
import 'dart:async';
Stream<double> doubleStreamer() async* {
for (var i = 0; i < 5; i++) {
yield i.toDouble();
}
}
void onData(args) {
print(args);
}
void main() {
var z = doubleStreamer();
z.listen(onData); // prints 0.0 - 4.0
}
// I. Isolates
// Instead of threads, all Dart code runs inside of isolates.
// Each isolate has its own memory heap, ensuring that no isolate’s state is accessible from any other isolate.
// think goroutines
// ref:: https://api.dartlang.org/dev/dart-isolate/dart-isolate-library.html
// II. Metadata
// used 2give additional info about your code.
@Todo('seth', 'make this do something')
void doSomething() {
print('do something');
}
// ref:: https://www.dartlang.org/guides/language/language-tour#metadata
// III. Documentation comments
// Inside a documentation comment, the Dart compiler ignores all text unless it is enclosed in brackets.
// Using brackets, you can refer to classes, methods, fields, top-level variables, functions, and parameters.
// The names in brackets become links u can click.
// ref:: https://www.dartlang.org/guides/language/language-tour#documentation-comments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment