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

> Thats AMAZING. The only languages have shorter grammars are core lisp/scheme.

It's nice, but I'm not sure I'd go with amazing. Most or all of Niklaus Wirth's languages have shorter grammars, for example. I'd imagine quite a few others do as well.

E.g. Oberon-2 has 33 EBNF productions: http://en.wikipedia.org/wiki/Oberon-2_(programming_language) - that fits fully on screen for me with my default font size...

Regarding Ruby, I agree. I'm working on a Ruby compiler, and "decoding" the MRI parser into something closer to optimal will still leave an awful mess no matter what you do. I love programming Ruby, but implementing it is hell (and one of the reasons I'm trying it...)



If you think parsing is the hard part, wait for the semantics. See, for instance, the Ruby examples on the Pyret home page.


I don't see any difficult semantics in those examples.

The hard part of parsing Ruby is mostly trying to conform to MRI rather than to a formal grammar. In comparison the semantics are reasonably simple.

It's hard to compile Ruby efficiently, though, but for reasons unrelated to those examples.

(Incidentally I don't know if that scoping example is intentionally ignoring the fact that Ruby does support lexical scoping (EDIT: for blocks), or if it's lack of understanding of what what "def" is.

The Ruby way of achieving what that example is trying to do is:

    def f(x)
      g = proc do |y|
        x + y
      end
      g[2]
    end
    f(2)
(g[2] is shorthand for g.call(2))

"def" explicitly introduced a method-level scope of the innermost wrapping class scope. Nesting 'def's is not in any way idiomatic Ruby. It's not necessarily very useful to nest them given those semantics. But "def" is really just syntactic sugar for #define_method, and so it is logical for it to work where #define_method does.

I might be inclined to agree that the different Ruby ways of defining blocks, methods and closures could do with some simplification. Allowing "def" to bind surrounding variables would remove a lot of the need for class instance variable or class variables, for example. )

EDIT:

Also, the currying example would look like this in Ruby:

    o = Object.new
    def o.my_method(x)
      self.y + x
    end
    def o.y
      10
    end
    method_as_fun = o.method(:my_method)
    method_as_fun[5]
You can argue for implicit currying if you want, but to me that's far more confusing. That said, it is extremely rare to find currying used in Ruby code.


Yes, I spoke too loosely. What I meant to say is that you'll have hard time making Ruby fast. I assumed implicitly that the point of writing a compiler was to optimize performance, though maybe not.


Thanks for the feedback.

Re: scope, you're right that using "def" the way I did isn't very idiomatic Ruby, but I always run afoul of it because it looks so similar to what I'd write in another language. I took that example down for the moment; I still have a personal gripe with it, but my "fundamentally broken" language was a bit strong. If I think of a more illustrative example, I'll put something back up.

The currying example I still think is weird in Ruby, and it's because it interacts bizarrely with the syntactic choice about optional argument lists. The thing that is wrong with JavaScript and Ruby is that they both have dot expressions and application expressions; o.m and f(x). It looks like

o.m(x)

should be a composition of dot lookup followed by an application, since both of those raw expressions make sense on their own. But in neither does the decomposition actually work:

m = o.m m(x)

There's no state or funny mutation going on here, but a simple kind of substitutability isn't working. JavaScript does it especially poorly, and Ruby has this awkward inability to decompose because of its choices about application syntax. Now, in Ruby I'm aware that with or without parens are actually both method calls, so it's not like there's a field access and an application in the underlying language model. But Ruby then adds the syntactic convenience of no arguments to make it look like access is possible, but that syntactic convenience is a bit of a leaky abstraction.

I should note that Python actually gets this nicely right IMO, and dot lookup curries self so this works out.

The underlying thing that irks me and I'm calling out here is the non-compositionality of what looks like two expressions that should compose. This is something we felt like figuring out and getting consistent for Pyret.


> Incidentally I don't know if that scoping example is intentionally ignoring the fact that Ruby does support lexical scoping (EDIT: for blocks), or if it's lack of understanding of what what "def" is

I also don't think it is fair to say that ruby "failed to nail lexical scope in fundamental ways".

I like how it enables lexical scoping with blocks, instead of enabling it in, maybe, more common way with embedded functions. To me, the ruby way is more intuitive.

Also, 'breaking scope' with block (that acts as anonymous function) instead of defining new (embedded) function feels more explicit wrt real scoping intentions.


I've done a fair amount of programming in Ruby (two reasonably large Rails applications, spanning about two years of development time). When switching to Ruby from just about anything else that I program in from JavaScript to Python to Racket to ML, I get tripped up on exactly this issue because it doesn't match my expectations at all.

My gripe is that the simplest, cleanest construct in the language for defining named functional abstractions---"def"---doesn't support closing over variables, which other languages do, so I have to warp my thinking a bit to program in Ruby. The analogous program in the four languages I mentioned above (and Pyret, and more) works and creates a closure. Maybe I just don't think well in Ruby, because I end up feeling frustrated that Ruby seems to not like functions.

All that said, "in fundamental ways" is a little harsh. At least in this example, Ruby hasn't done anything to violate the integrity of static scoping the way, say, JavaScript's "with" does. I'll try to see if I can come up with a better example that's a clearer problem and less a personal dislike.


agreed, having decent semantics is key. :)




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

Search: