• dynamic scoping
  • |> operator like F#
  • CSP-like model
  • haskell like combinator stuff
  • implicits
  • restricting combinations of covariance and contravariance
  • ML/Haskell style partial application
  • active patterns
  • pattern matching against open types
  • really good, prescriptive, error messages
  • metatype
  • anonymous types
  • type aliases

Direct approach to purity

functions, methods, and modules are either:


    throw x             -- compiler support/inference
    nothrow             -- compiler support/inference
    pure                -- compiler support/inference
    total               -- compiler support/inference

policies are attached to things as attributes. they are checked recursively at compile-time

there seem to be three operations that can be done with these:

  • claim -- claim that a method meets a constraint
  • assert -- assert a constraint. ignore evidence to the contrary

how do you make this stuff user-extensible

module ...
    let ... (define function)

type class ...
    let ...

Compile time computation

really interesting.

alexandrescu loved it about d. I love it too, but we can do better.

compile time module imports cause code to run inside of the compiler!

caching compiler-server is the preferred way to build standalone compiler should be as fast as possible for other users

clear separation between identity types and structural types

don't tie the idea of identity and the idea of references together like clr

TODO: look at GADT's again and decide what to steal

feelings: scala's approach to this is too obtuse. GADTs are neat directly.

Maybe sums should use a GADT-like encoding always to emphasize their generality

What does a meta-type look like?

interface MetaType equals? : Type -> bool subtype_of? : Type -> bool end

Possible macro syntax (presumes statements)

macro stmt 'for' '(' (init:stmt) ';' (cond:expr) ';' (end:expr) ')' (body:stmt)
    goto cond
        if ,cond then
            goto top
        goto loop

pain point: macro names vs identifiers can create ambiguity. Almost seems like they should be in separate namespaces but this is syntactically hard

Call sites with bidirectional data flow are evil.

Execution model simple enough for computation expressions, (but static?), (but composable?)

Think about hybridization of C++ const and "real" immutability.

  • const_cast is bad. const should be unbreakable.

but do people really understand const...really?

The problem with object orientation is twofold:

  • some program objects have no correspondence in the real world
  • some real-world objects can-not be accurately represented in the program

that's it. We need good building blocks, not philosophy. Programs are not about modeling real world objects. They're about building virtual stuff.

trace is really important. example is incomplete matches:

match async_api foo bar with
    | Success(x)        =>
    | *                 => true)

Canonical code formatting rules


tool to enforce

Banging out binding syntax...incomplete

// let bindings bind lexically scoped identifiers
let x = 4
let x = 5       // ok to shadow
let rec f = ...

// defines lexically scoped function
let rec map f Nil          = Nil
            f (Cons hd tl) = Cons (f hd) (map f tl)
    where map : (a->b) -> List a -> List b

let rec map :: (a->b) -> List a -> List b =
    | f Nil          = Nil
    | f (Cons hd tl) = Cons (f hd) (map f tl)

let rec map (f : a -> b) (l : List a) : List b =
    l match Nil        -> Nil
          | Cons hd tl -> Cons (f hd) (map f tl)

def map(f : a->b, l : List[a]) : List[b] =

let rec map func list =
    list match Nil        -> Nil
             | Cons hd tl -> Cons (f hd) (map f tl)

let rec map func list = list match Nil        -> Nil
                                 | Cons hd tl -> Cons (f hd) (map f tl)

let map f l = match l with
                  | Nil        -> Nil
                  | Cons hd tl -> Cons (f hd) (map f tl)

let foo () =

// var bindings bind lexically scoped variables
var x <- 4
x <- 5
Comments powered by Disqus