Hacker Newsnew | comments | show | ask | jobs | submit | tonyg's comments login

Nice article. One thing that people are doing these days is using the #lang mechanism to easily turn a Redex [0] model into a quick-and-dirty prototype implementation of a new language, integrated with the Racket tooling (IDE etc.).

[0] http://docs.racket-lang.org/redex/tutorial.html

-----


All those home routers. All those home routers running Linux. All those home routers that are difficult to upgrade. All those home routers that will soon be part of some botnet or other?

-----


Those (Linux-based) home routers usually use uclibc, which is not glibc.

Similarly, they usually use busybox ash as a shell and thus weren't vulnerable to shellshock.

Some do use openssl, so might still be affected by heartbleed.

-----


Good point! Hooray for avoidance of software monocultures.

On the other hand, I shall now work hard to stop worrying about undiscovered vulnerabilities in uclibc.

-----


But it is still C code, so...

-----


If they aren't already a part of a botnet.

-----


Does anyone have any insight into how Orleans handles failure? The only mentions I found in the documentation suggest that "grains cannot fail", which seems fairly odd to me. What about exceptions? Can grain state become corrupted? How does the system recover? Is there anything like Erlang's links or monitors here? Are supervisors relevant at all in this system?

-----


In Orleans an actor cannot physically fail, just like an object in a process cannot fail. If an unhandled exception is thrown by actor code, the runtime will deliver the exception to the caller and break the TPL task of the call. Actor code is free to logically fail, e.g. by catching an exception, detecting an internal inconsistency, etc., and can handle such a case any way it wants. For example, it can set an internal failure flag and/or ask runtime to deactivate it immediately.

I guess it's a bit of a philosophical question - what is considered a failure. Orleans doesn't impose its own definition of that on actors.

-----


There was a build 2014 session on how it works...it was pretty in depth. The video is on channel 9.

-----


I couldn't find the original but this gets into it a bit:

Using Orleans to Build Halo 4’s Distributed Cloud Services in Azure http://channel9.msdn.com/events/Build/2014/3-641

-----


List of investment trends, or Black Mirror bingo card?

-----


Artist/architect Friedensreich Hundertwasser had some similar ideas about burying highways and using parkland to absorb some of their emissions, both chemical and auditory - his "invisible, inaudible Green Motorway":

* http://www.pithandvigor.com/wp-content/uploads/2012/12/under... (linked as part of this blog post: http://www.pithandvigor.com/diy-projects/materials/friedensr...)

* http://www.hundertwasser.com/arch/view-25slashXIII

* http://www.hundertwasser.com/arch/view-25slashXII

* http://www.hundertwasser.com/arch/view-25slashV

-----


In Linz (Austria) there is a similar highway with a park above it (more than one kilometer long). Built in 2005, water leaks into the tunnel and there are high costs to fix it (including removing the park to fix the problems).

http://derstandard.at/1310511908137/Undicht-seit-Eroeffnung-... (German)

-----


Water leaks into all tunnels. Some have this issue in a more problematic way that others, admittedly ;-)

-----


I like the idea very much, and the brevity and clarity of the implementation is pleasant. However, there are a few problems with it:

  \\/"-
   \_/   wren v0.0.0
  > var F = new Fn { | x | F.call(x + 1) }
  > IO.print(F.call(10))
  Segmentation fault
This shows two things. (1) it's not yet a "safe" language implementation; (2) it doesn't support proper tail calls. Both are fixable, of course, but the lack of proper tail calls is a Bad Language Smell.

Its syntax is also a little strange. The following isn't accepted by the parser:

  var F = new Fn { | x | if (x == 0) { return x } else { return F.call(x - 1) }}
  IO.print(F.call(10))
but the same file with extra newlines is accepted just fine:

  var F = new Fn { | x |
      if (x == 0) {
         return x
      } else {
         return F.call(x - 1)
      }
  }
  IO.print(F.call(10))
It also makes me a little sad that

  var F = new Fn { 0 }
returns 0, while

  var F = new Fn {
      0
  }
returns null.

-----


> (1) it's not yet a "safe" language implementation;

Not yet, but it's getting there! I have to fix this:

    // TODO: Check for stack overflow.
On line 335 of wren_vm.c. The actual fix is pretty straightforward. You just store the maximum stack height with each function and check that that doesn't overflow on a call. I just haven't gotten around to it.

Wren should be pretty good about most other boundary case behavior. If not (and like this issue too!) it's a high priority bug. Your scripting language shouldn't crash!

> (2) it doesn't support proper tail calls. Both are fixable, of course, but the lack of proper tail calls is a Bad Language Smell.

That's correct. I have implemented TCO before. Wren's predecessor Finch supported them. Fibers in Wren already support an analogous feature.

My current thoughts are that I likely will support this, but it will be explicitly opt-in. Instead of having the tail call automatically be detected and eliminate the parent stack frame, you'll have some specific syntax to say "this is a tailcall".

This is for two reasons:

1. Most of the time, having a useful stack trace is really handy for debugging. For better or worse, stack traces are a standard tool for most users to understand when their code does something wrong.

Eliminating all tail calls hurts this with little benefit in the majority of cases where you aren't doing any recursion (mutual or otherwise) and will never blow the stack.

Of course, you can do clever things to regenerate stack traces while still doing general TCO, but that adds a lot of complexity and simplicity of implementation is an important feature.

2. With a language that has a non-sexpr syntax, it can be very hard for a user to tell which call actually is the tail call. Consider something like:

    {
      return (foo.bar + !baz).call ? some.thing : other / wise
    }
Can you quickly identify if this code won't blow the stack or not? If a user comes along and makes some tiny change to that statement, can they be confident their program won't start failing on larger inputs?

Given that, I think it's good to visibly call out "Hey, there's a tail call here. It's important!" in the source code. I'm not sure what the syntax will look like yet, but that's my intent.

    var F = new Fn { | x | if (x == 0) { return x } else { return F.call(x - 1) }}

Designing a syntax that's simple, expressive, and beautiful is tricky! Coming up with one that's easy to compile with a single pass compiler is even more tricky.

In this case, because you don't have a newline after the "|", it is looking for an expression body. "if" is a statement, not an expression. There's a bunch of ways this could be improved:

1. Certainly, the error message should be better!

2. We could make "if" an expression. We could make everything an expression for that matter, though there's some pros and cons there.

3. If could allow statement bodies in single-line functions.

> but the same file with extra newlines is accepted just fine:

Yup. This is probably the most unusual corner of Wren's syntax. It's documented here:

http://munificent.github.io/wren/syntax.html#blocks

The constraints I'm working with are:

1. I wanted a terse way to define single-expression members and functions that return their result.

2. I'm not a fan of implicit returns in larger bodies. I don't like the idea of methods implicitly leaking the result of their last expression even when that isn't intentional, and I think it tends to lead to less efficient bytecode.

So I tried to come up with a specific syntax for a single-expression body. Other languages use stuff like "=>", but I wanted to try to not add more punctuation.

Since newlines are already significant in the language, I figured I'd try using the newline after "|" or "{" as the signal.

So far, I personally like how it feels, but feedback from others like you is definitely helpful. If it rubs a lot of people the wrong way, it's easily changed.

-----


> 1. Most of the time, having a useful stack trace is really handy for debugging. For better or worse, stack traces are a standard tool for most users to understand when their code does something wrong.

> Eliminating all tail calls hurts this with little benefit in the majority of cases where you aren't doing any recursion (mutual or otherwise) and will never blow the stack.

In "Finding the Needle"[0], SPJ et al came up with a nice stack trace representation for GHC that handles recursion. Not sure if you've seen the paper, but it might be worthwhile if you haven't (section 4, specifically).

[0]: http://research.microsoft.com/en-us/um/people/simonpj/papers...

-----


> 2. We could make "if" an expression. We could make everything an expression for that matter, though there's some pros and cons there.

I'm not sure if this is the place for such a far-reaching discussion, but I've never understood this point. What are the cons to making everything an expression?

-----


Here's a bunch of Pythonistas grappling with this question:

https://mail.python.org/pipermail/python-ideas/2008-Septembe...

-----


Until recently I was firmly in the "statements are evil" camp. Now my perspective is a bit more nuanced. There are two facets to "everything is an expression":

1. Any grammatical production can be used in an expression.

2. Function/method bodies implicitly return the result of the last expression they contain.

I really like #1, though even expression-oriented languages limit this. There's still something akin to "operator precedence" at the "statement-list" expression level. If, for example, you look at Ruby's grammar, you'll see it has productions called "statements".

This is to rule out totally bizarre things like:

    1 + while (foo) { ... }

    for (for (for (...) {}) {})
So, even if you treat everything as an expression, there are still some limitations as to where different grammatical productions can appear.

In practice, I think the main thing you gain (in a language with an imperative-style syntax like Wren, Ruby, etc.) is the ability to have the right side of a return or assignment be a branching statement. Stuff like:

    var fizzBuzz = if (n % 15) {
      "FizzBuzz"
    } else if (n % 5) {
      "Buzz"
    } else if (n % 3) {
      "Fizz"
    } else n
The other statements are less useful. I'm not even sure what the result of a looping expression should be, but I'm certain that I don't like CoffeeScript's answer (an array of all of the elements, which often gets discarded!). Break and return statements have no useful results. Variable declaration statements make it really hard to reason about scope when used in the middle of an expression.

All this means that I think loosening up the grammar to make every statement an expression is mostly only useful to make branching an expression.

The other half is having functions implicitly return the result of the last expression. I really like that in some functions for brevity, and really dislike it in others. This may not be rational, but creeps me out that lots of Ruby methods just leak random values.

For me, I'd rather have an explicit form for bodies that implicity return their result and have the default be to not do that. So that's what I did for Wren. A single-line body implicitly returns its result, but a multi-line one does not:

   class Person {
     name { "Fred" } // Implicit return.

     sayHi {
       IO.write("Hi, I'm Fred!")
       // Returns null.
     }
   }
I like this more than always having an implicit return, so this addresses point #2 above. I'm not opposed to allowing branch statements to be expressions, but I worry that the confusion it causes may outweight the benefit, so I conservatively left it out for now.

Having a statement/expression distinction also makes the bytecode compilation a bit simpler. It's easier to tell which things emit values and which don't, but that's not hard to fix.

-----


> For me, I'd rather have an explicit form for bodies that implicity return their result and have the default be to not do that. So that's what I did for Wren.

That strikes me as an excellent decision.

> A single-line body implicitly returns its result, but a multi-line one does not

That, i'm sorry to say, does not! Assigning different semantics to two passages of code whose only syntactic difference is in the composition of their whitespace seems like it might be a misfeature.

Is it too late to consider a louder way of marking the difference? How about:

    name = { "Fred" } // implicit return
Or even just introducing a terser explicit return:

    name { = "Fred" } // explicit but barfulous return
    name { ^"Fred" } // explicit return, also homage to Smalltalk

-----


> Assigning different semantics to two passages of code whose only syntactic difference is in the composition of their whitespace seems like it might be a misfeature.

I'll admit it's a bit iffy. However, newlines are already significant as statement separators, so this isn't totally outside the bounds of reason.

    name = { "Fred" } // implicit return
This looks a little too similar to a setter definition to me. Also, it makes sense here, but would look really strange for a lambda:

    people.map {= |person| person.name }
The typical solution is "=>", like:

    people.map (person) => person.name
But then without a trailing delimiter, it's hard to chain multiple of these calls together, which is really common in list manipulation.

-----


> I'm not even sure what the result of a looping expression should be

This is one of the reasons I like having proper tail calls be part of a language specification, incidentally :-)

Reason being that loops are then simple derived constructs, and their meaning (as expressions and otherwise) follows from their definition.

In the specific case of "while", the value of a while-loop-like form would usually be null/void, because of the one-armed-if it expands into.

Regarding implicit return values: in your example, the sayHi method would naturally return null if IO.write returned null, even with implicit return values. Having a strong library convention that imperative procedures return null seems to prevent programmers from trying to rely on the results of imperative procedures, even where implicit return values are part of the language. My support for this claim is only anecdotal; it comes from working with programs written in Racket, which has both implicit return values and a strong convention of returning void from imperative procedures.

-----


> In the specific case of "while", the value of a while-loop-like form would usually be null/void, because of the one-armed-if it expands into.

Right, which doesn't make it very useful as an expression.

> Having a strong library convention that imperative procedures return null seems to prevent programmers from trying to rely on the results of imperative procedures

I have the opposite feeling (possibly because Wren doesn't have implicit returns). Since library calls are expressions, they may as well return something useful when possible.

For example IO.print() returns its argument. That's handy for debugging the result of an intermediate expression. Say you've got:

    someMethod(anotherOne(arg))
And something weird is going on. Giving IO.print() a return value lets you inject it in the middle:

    someMethod(IO.print(anotherOne(arg)))
without having to hoist the subexpression out.

> My support for this claim is only anecdotal; it comes from working with programs written in Racket, which has both implicit return values and a strong convention of returning void from imperative procedures.

Yeah, that makes sense. I think the important idea is to be consistent.

-----


> I'm not even sure what the result of a looping expression should be

>Break and return statements have no useful results

The result of a looping expression could be specified by its break!

    var myNeedle = foreach(var maybeNeedle in myHaystack) {
        if (maybeNeedle.isTheNeedle()) break maybeNeedle;
    }
    if (myNeedle != null) print("I found " + myNeedle.toString());

-----


I quite often find myself writing code like (in Java):

  Fruit edibleFruit = null;
  for (Fruit f: basket) {
    if (f instanceof Banana) {
      if (!f.isDiscoloured()) {
        edibleFruit = f;
        break;
      }
    } else {
      if (!f.isMouldy()) {
        edibleFruit = f;
        break;
      }
    }
  }
And getting rid of the nasty assign/break pairs by extracting a method:

  Fruit edibleFruit = edible(basket);

  Fruit edible(Collection<Fruit>: basket) {
    for (Fruit f: basket) {
      if (f instanceof Banana) {
        if (!f.isDiscoloured()) return f;
      } else {
        if (!f.isMouldy()) return f;
      }
    }
    return null;
  }
But your idea would let me clean up without having to extract a method (here, in a hypothetical Java-with-value-bearing-break):

  Fruit edibleFruit = for (Fruit f: basket) {
    if (f instanceof Banana) {
      if (!f.isDiscoloured()) break f;
    } else {
      if (!f.isMouldy()) break f;
    }
  }
You need to have a story about what happens if there isn't a break - if the loop exits normally. You could implicitly return null, but that's a terrible idea. Better would be to require else clauses on value-returning loops (a bit like the else clauses that Python allows on try blocks):

  Fruit edibleFruit = for (Fruit f: basket) {
    if (f instanceof Banana) {
      if (!f.isDiscoloured()) break f;
    } else {
      if (!f.isMouldy()) break f;
    }
  } else null;
Yes, i'm still returning null here, but at least i have to do it explicitly, which makes me feel bad about it and think about finding a better alternative!

-----


I like this idea. :)

-----


When you say that there are drivers missing, does this go as far as GPL violations? Or is it not quite as toxic as that?

Also, what is the situation like with regard to figuring out what has been changed in a vendor-supplied kernel vs. a generic kernel source tree? Is it reasonably straightforward to get a clean diff so you can see what was changed? Non-upstreamed hacks and bodges seem less terrible to me if it's possible to at least see how they work.

-----


Not necessarily GPL violations (there are cases of those too, but the bulk of it is not). It's just a matter of nobody having cleaned up the drivers enough to get them submitted for upstream inclusion. It can be quite a bit of work to do, and the next generation of product is sitting there waiting on the same people to make that work instead.

You can usually download and diff the source tarballs. Some vendors keep git repos so you can see changelogs as well. There's usually a lot of noise in there though, lots of various imported vendor drivers that duplicate things, firmware files in hexdump format, etc. It's pretty common to see diffs of millions of lines.

-----


could you elaborate on what you mean by "cleaning the drivers" ?

I'm really curious, because it seems that Android has built an architecture where vendor supplied drivers (binary blobs?) can be dropped in without too much changes. But upstream linux needs a considerable amount of rework to "absorb" a driver.

Is this deliberate (the same reason why GCC is obfuscated) or is there a technical reason behind it ?

Because Android Linux works on thousands of different platforms with a lot of stability - I'm beginning to think that the Android driver model is superior... and perhaps mainstream Linux would do well to move to that.

-----


I work on an embedded Linux device. Sometimes, we do whatever nasty hack we need to make this kernel work on that device -- but those changes aren't portable, aren't maintainable, and don't meet the quality requirements to be in the upstream tree.

There can also be a perception it's "a waste of time" since "nobody will run another kernel on this anyways"

-----


Thanks. The noise issue sounds pretty frustrating.

-----


To those downvoting: it's a reference to a META tag that Olin put in the HTML:

  <meta name="keywords" content="Scheme, programming language, list processing, SRFI, underage lesbian sluts">

-----


I like the visualizations of the stack behaviour.

-----


By transclusion. You'd cache the big, reusable chunks of content, and serve up a fresh transient little document that transcluded both the larger content chunks and the dynamically-included advertisements.

-----

More

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact

Search: