Live data from Hacker News

Another go at the Next Big Language

dave.cheney.net

111–120 of 125 posts

Re: Another go at the Next Big Language

#111

I was really excited about Go. Designed by some gurus, seemed to get everything right, google app engine supported it. Then I tried to build something. Java-like verbosity. Meh, I can deal with it. []byte and string aren't the same. Whatever, a few extra lines and thot cycles here and there, no big deal. Overly complex library functions. Let me explain this one. In Lua, markdown (discount) is a single function. In Go…

This is the first time I've heard "Java-like verbosity" as a criticism of Go, and I'm baffled by it. Go is generally much more succinct than C++, Java and other similar statically typed languages. Can you expand on your comment?

everything is package prefixed, names are long.

Totally minor, but reminded me of my days with java

Re: Another go at the Next Big Language

#112

Here's the core problem with next generation languages. Languages that come out of academia focus too much on syntax and computer science level functionality, and it's extremely rare for a language of that sort to make it in the real world. The languages we use today either come from big companies with the ability to promote anything long enough to get traction on any language that is at least "good" or they come fro…

D has profiling and unit testing built in (also coverage analysis and documentation generation), but I'm curious how you'd see source control built in.

Re: Another go at the Next Big Language

#113

Earlier quoted context omitted.

> OK, so I suppose the next question becomes what “test it” means. It would be something similar to all possible code paths being executed with the program in all possible states. Heck right now I'd settle for even a small subset of this. > Or maybe you’re thinking of some sort of automatic simulation of possible failure cases when you get to the open/read/write/close operations, serving a similar roles to things lik…

It is already known that open/read/write/close can fail. They are quite difficult to force to fail, so currently you have to write a lot more code to make that happen. And it gets really tedious once you look at all the combinations. eg open has to fail, open has to succeed and then read fails, open succeeds and the 3rd read fails and on and on. OK, I’m following you so far. Assuming that (a) our language lets us spe…

At the moment the error handling code for cat would be looking at failures for all 4 functions. Unless they fail that error code doesn't even get run.

My test code currently has to put the program into a state where cat can be called, and then has to mock/augment each failure point, and then check the results. Just having the middle piece (mock/augment) done automagically would be a massive help. And then of course cat itself can fail so each of its callers needs a way of testing too. Some hand wavy combination of convention over configuration, documentation and annotations would likely help.

Even the state issue should be automatable in many circumstances. For example you could make a successful run of the program, and then the magic records state at the entrance to code blocks. It can cause each failure circumstance, rewind state to known good and cause the next failure circumstance etc.

I'd even be happy running my code (with no error handling) under some tool that induces the errors - when they aren't handled it asks me what I want to do which typically involves writing code to handle the issue, which it then directly integrates and keeps running until the next error.

Even test pass/fail can be somewhat automatable. The tool records what happens, and then in the future alerts you when there is a difference in behaviour. The response is either that the issue needs to be fixed, or that the new behaviour is correct.

Re: Another go at the Next Big Language

#114

Earlier quoted context omitted.

> LuaJIT is faster anyways. This man speaks the truth. Well, actually, I know nothing about Lua. But I do know that Go currently isn't very fast. I mean, compared to highly dynamic languages the performance is fine. But compared to C++ or even modern JVM it's meh. I feel like there's going to be improvement here, though, and I wouldn't be surprised if the versions of golang used internally at Google aren't faster. My…

When you say that Go currently isn't very fast, maybe you should try coding something in it. I found it to be suprisingly fast. I think if you are doing a lot of memory allocation, then the garbage collection may slow you down, but I wouldn't be suprised if it's still faster than a jitted language like LuaJIT.

My largest Golang deployment is a blender service. That's where I used the Goroutines and protocol buffers I mentioned earlier.

Its speed is acceptable. My take on it is that this is a new language. Of course it doesn't have fully mature, fully optimized internals. And certainly part of the problem is that I haven't developed a full mastery of the language (Mastery is not a word i use lightly) so that will improve, too.

But if your experience is that you've built multi-threaded apps in Go that perform comparable to a c++ implementation then I'd love to know if you have any specific tips and also I suppose that means that we're not going to see any broad improvements in runtime performance?

Re: Another go at the Next Big Language

#115

Earlier quoted context omitted.

Of all the programs out there that people and businesses need to have, in what languages was the majority written? Do proponents of older, supposedly superior languages have an equal body of work to show for it? The obvious flaw of this approach is that the majority of people might have written their software in a less than optimal language for reasons unrelated to productivity. Proponents of niche languages, almost…

> The obvious flaw of this approach is that the majority of people might have written their software in a less than optimal language for reasons unrelated to productivity. Proponents of niche languages, almost by definition, never have a body of work to show that is equal to that of the mainstream languges. I'm not expecting equal bodies of work. Just show something. Forget the enterprise, big companies and such. How…

There certainly are other factors than a language's productivity. I don't dispute that at all, or I wouldn't be writing so much code in C++.

But I think language popularity has very little to do with productivity or any other rational factor. Languages mostly piggyback on platforms that emerge rapidly at some point in history.

C came with Unix. JavaScript and Java came with Web browsers. SQL came with relational databases. Objective-C became widely used (if not poplar) with the iPhone. PHP came preinstalled with shared web hosting. C# comes with Windows. VBA comes with Office, etc.

Developers mostly just choose platforms not languages. Whoever makes the platform decides on the language and it will be "popular" regardless of how atrocious it may be.

And by the way, PG is building something today and he's building it in a Lisp dialect (http://paulgraham.com/arc.html)

Re: Another go at the Next Big Language

#116

Earlier quoted context omitted.

When you say that Go currently isn't very fast, maybe you should try coding something in it. I found it to be suprisingly fast. I think if you are doing a lot of memory allocation, then the garbage collection may slow you down, but I wouldn't be suprised if it's still faster than a jitted language like LuaJIT.

My largest Golang deployment is a blender service. That's where I used the Goroutines and protocol buffers I mentioned earlier. Its speed is acceptable. My take on it is that this is a new language. Of course it doesn't have fully mature, fully optimized internals. And certainly part of the problem is that I haven't developed a full mastery of the language (Mastery is not a word i use lightly) so that will improve, t…

I recommend trying gccgo, the Go compiler for the GCC suite. (GCC 4.7.1 and later have Go built in.)

In my experience it is (at -O2) much faster than Go's own compiler. GCC, after all, has because a bunch of advanced optimizers with a long history of development behind them, and Go's own compiler does not.

My recolleciton is that Go's own compiler was intended as a "suboptimal but correct" reference compiler, but this may have changed.

Re: Another go at the Next Big Language

#117
post #88

Earlier quoted context omitted.

> Using "let" for this in Clojure results in nested and realatively less readable code. Why would you have to have nested code? Why can't you just do this: (let [a foo, b bar, c (combine foo bar)]) > Are macros such a nice feature that they justify S-expressions? I'd say S-expressions are the nicest looking syntax, which justifies them regardless of their considerable practical advantages. The only reason you might t…

What I meant was this: (let [x (math/sqrt (+ 256 (* a a))) y (math/log (- (+ a b) (/ 1 (+ a (* b b b))))] (* 2 (+ x y))) In other languages I would do something like this: x = math/sqrt(256 + a * a) y = math/log((a + b) - (1 / (a + (b * b * b)))) 2 * (x + y) As for static typing - in combination with IDE support, it's really useful in larger projects.

I made a reader macro (not technically supported by Clojure, but I don't care) for these situations that provides something I call the "scoping operator".

    #>a 6
    #>(let [b 7])
    #>(while true)
    ...
Using this operator, the above code is then equivalent to the below code, which I find much easier to deal with for code that is strictly linear in execution semantics.

    (let [a 6]
        (let [b 7]
            (while true
                ...)))
I don't use it for most functions, however, only those where I find myself otherwise ending up in nested expression hell. When I do, however, it works perfectly with other language features (example: doing a syntax quote on a #> works exactly as one would hope; it is conceptually just a fancy macro).

(...and where breaking up the logic into smaller functions would just obfuscate the process, as the steps fundamentally could only be called from a single place anyway, turning the nesting into an even-worse problem of broken apart logic.)

Re: Another go at the Next Big Language

#118
post #88

Earlier quoted context omitted.

> Using "let" for this in Clojure results in nested and realatively less readable code. Why would you have to have nested code? Why can't you just do this: (let [a foo, b bar, c (combine foo bar)]) > Are macros such a nice feature that they justify S-expressions? I'd say S-expressions are the nicest looking syntax, which justifies them regardless of their considerable practical advantages. The only reason you might t…

What I meant was this: (let [x (math/sqrt (+ 256 (* a a))) y (math/log (- (+ a b) (/ 1 (+ a (* b b b))))] (* 2 (+ x y))) In other languages I would do something like this: x = math/sqrt(256 + a * a) y = math/log((a + b) - (1 / (a + (b * b * b)))) 2 * (x + y) As for static typing - in combination with IDE support, it's really useful in larger projects.

In the C-based languages that you apparently familiar with there are several control statements that aren't expressions like for, if, while, and do. For example, here is how you can use the if statement in C:

  if (a >= 0) {
    printf("Positive");
  } else {
    printf("Negative");
  }
  
The if control statement in C can only be used to induce side effects, such as printing to stdout, it can not be used for functional programming. On the other hand, Lisp is an expression oriented language, so expressions such as if can be used as values for functional programming:

  (if (
The same principle applies to the let statement. It is an expression so that you can use it without ever resorting to creating mutable state or inducing side effects. If you allow emacs to automatically handle the nesting involved with your statements, then there it shouldn't really be an inconvience. However, when you need global mutable state use def:

  (def x (Math/sqrt (+ 256 (* a a)))
  (def y (Math/log (- (+ a b) (/ 1 (+ (* b b b))))
  (prn (* 2 (+ x y)))
Clojure encourages good practices like avoiding local mutable state. That said, if you want to you can always create your own local environment to declare local mutable state:

  (defmacro defun
    [name args & code]
  
    `(defn
       ~name
       ~args
       (with-local-vars [~(symbol 'e) {}]
         (let [~(symbol 'def*!)
               (fn [p# v#]
                 (var-set ~(symbol 'e) (assoc (deref ~(symbol 'e)) p# v#)))]
             ~@code))))
           
Here is an example of code like yours using this macro and a local environment called e:

  (defun func
    []
    
    (def*! 'x (Math/sqrt (+ 256 (* a a))))
    (def*! 'y (Math/log (- (+ a b) (/ (+ a (* b b b))))))
    (* 2 (+ (@e 'x) (@e 'y))))
	
You could probably make that look nicer using macrolet and by definining other new macros and operations.

Re: Another go at the Next Big Language

#119
post #19

I have to agree with the commenters on that article that JavaScript is the next big language. With HTML5 it's pretty amazing what you can do with JS. It's reached the point of being nearly as powerful as any thick client technology yet with ubiquitous browser and OS support. It performs fairly well too: http://shootout.alioth.debian.org/u32/javascript.php . I'm not sure why one test is 100x slower, but the rest are <…

>>I'm not sure why one test is 100x slowerSee http://stackoverflow.com/questions/7025286/why-does-this-v8-...

Re: Another go at the Next Big Language

#120
post #95

Earlier quoted context omitted.

I don't think it would be that nice. For good error reports back to the user, you'd have to have a fairly large amount of logic in the catch block. If you have a function that copies data from one file to the other and catch some sort of IOException, you'd end up trying to analyse what it is to report it properly. After all, it could be either one of the files, while opening, closing, reading, writing, ...

_For good error reports back to the user, you'd have to have a fairly large amount of logic in the catch block._ Serious question. How is that a reason to have that _amount of logic_ in the function body? Having IDE/editors which can fold blocks of code and having the catch blocks collapsed by default will make code reading/understanding of code easier. IMO. Actually, I may try something like makng the try-cacth the…

I think that putting it in the body actually reduces the amount of code and makes it more readable. Compare something like this (ignoring naming, formatting, made up language, etc. I want to show the structure only):

    fin=open(fin_name)
    fout=open(fout_name)
    ...
    catch IOError e
      if e.call == 'open'
        if e.filename == fin_name
          log_error "cannot open input ..."
        elif e.filename == fout_name
          log_error "cannot open output ..."
        else
          log_error "cannot open file, but filename unknown"
      elif e.call == .....
        .....
to something like this:

    try
      fin = open(fin_name)
    catch IOError
      log_error "can't open input ...."
      return

    try
      fout = open(fout_name)
    catch IOError
      fin.close()
      log_error "can't open output ...."
      return
Both are ugly, but I really wouldn't like to be the person trying to match up the error handling from the first example to the exact places in the function body. I'm not even sure what would this look like if the exception was coming from somewhere deeper in the function. open() is easy because we know how it fails. More complex call chains would be a challenge to even match up to the place they happened.
Post reply on HN