Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Haskell also has definitions, which can't be used as expressions directly, e.g. we can write:

    foo = bar
But we can't write:

    baz = 2 + (foo = bar)
I this case we can get the expected return value by using 'let... in...' syntax, but we wouldn't get the top-level definition, e.g.

    baz = 2 + (let foo = bar in foo)
Likewise for type definitions, class definitions, etc.

One language which handles definitions nicely as expressions is Nix. Nix has 'let' but I never use it. Instead we can use 'with':

    with {
      foo = bar;
    };
    "hello " + foo
The thing in braces isn't a block of statements; it's a key/value dictionary (Nix calls them 'attribute sets' or 'attrsets'). The 'with...; ...' syntax acts like 'let... in...' but both pieces are expressions.

    with {
      myAttrs = {
        foo = bar;
      };
    };
    with myAttrs;
    "hello " + foo
Interestingly, whilst Lisp distinguishes between 'letrec' and 'let' (bindings with and without mutual/self-reference, respectively), Nix distinguishes between 'rec {...}' and '{...}' (attrsets with and without mutual/self-reference). In other words, when we write 'with rec {...}' the 'rec' modifier affects the definition of the attrset (the '{...}'), it doesn't affect the binding of that attrset into the environment (the 'with'). For example:

    with {
      bar = 42;  // To prevent nonRecursive complaining about a missing variable
      recursive = rec {
        foo = bar + 1;  // The number 6, since 'bar' is taken from this 
        bar = 5;        // The order of definitions doesn't matter
      };  // The attrset { foo = 6; bar = 5; }

      nonRecursive = {
        foo = bar + 1;  // The number 43
        bar = 5;
      };  // The attrset { foo = 43; bar = 5; }
    };
    // [] is syntax for a list
    [
      (with recursive;    foo)  // The number 6
      (with nonRecursive; foo)  // The number 43
    ]  // The list [6 43]
Of course, attrsets (recursive or not) can be used as expressions:

    (rec { foo = bar + 1; bar = 5; }).foo  // The number 6


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: