Hacker Newsnew | past | comments | ask | show | jobs | submit | estavaro's commentslogin

I was a bit overwhelmed by the many samples that I clicked on.

Someone else posted a link to her GitHub repo and I was glad to check it out some. I chuckled at her using of Ruby/Rails. I was amazed at her using of jQuery.

It pains me to note that what the industry might consider sound software engineering is so detached from the creative tools that she has employed to get this going.

On one hand the industry demands greater quality from their tools. On the other hand the industry seems eager to provide the creative tools used by amateurs-alike to help to get people trained in the tools that the industry might need.

JavaScript really is a puzzle that the industry has been trying to solve. Because JavaScript is far away from what the industry might consider sound engineering principles. But users of JavaScript could make for great employees, so the industry has been trying to figure out a way to create a bridge between the two.

Keep up the great work! I liked playing the Hangman.

Cheers.


And that would be anti-social behavior by itself, right? :-)

Other people think that inmates are anti-social people. But were they always anti-social? Or just some of the time? And how is anti-social measured? Do extroverts make less anti-social people? And if so, does it matter that many inmates are also extroverts?

Bureaucracy seems to be incredibly painful in the Justice system. Decisions get made. To reverse those decisions it becomes a problem in itself. To err is human? To persist on it is stupid. Or is it just a bureaucratic mare?


My confession on the matter: Working with OO in JS made me a "cargo cultist." I wasn't entirely aware of how it worked, but just glad that it did for as long as I had used it. The last JS library I used was PrototypeJS which had some custom support for classes.

I learned about non-OO JS code in the YUI framework. I didn't like what I saw as it precluded a lot of "private and hidden" code.

I've deposited a lot of goodwill on the Dart language that compiles to JS. My reward is that Dart has library and class support that "just works! (TM)" Then again, I abhor the using of types that Dart allows as I think people waste a lot of time giving types to APIs and obscure the intention of the code, ultimately making the platform less popular.


>I think people waste a lot of time giving types to APIs and obscure the intention of the code

What do you mean? Adding types to the surface area (arguments and return types) removes a lot of friction.

I'm using jQuery for a couple of years. I still have to look at its docs almost every day I use it. Today, I had to check if the "selector" argument of "children()" is optional (spoiler: it is).

Also, having the type annotations there makes the intention so much clearer. The name and the type of the argument is usually all you need to figure out what it does.

I really like that about Dart.


The problem is that it makes people more concerned about getting the types right than about giving people shortcuts.

The API designers end up creating a multitude of APIs to deal with different type parameters and so on, to get their "generics" right and so on.

It makes the APIs look like Java APIs more than they jQuery ones.

Part of the problem is that the designers really want to get the types of classes and so on right on their parameters and return types. The types go beyond the primitives.

I've been able to watch it unfold and it's rather painful. The result looks less like a scripting language API and more like a C# collection of libraries, for better or for worse.


> giving people shortcuts

I don't see any problem there. The code is very compact. There are lambda expressions, method cascades, and user defined operators.

Also, structure is baked in. You don't need any of that AMD boilerplate code. Annotations are also baked in. You don't need to write those lengthy doc comments.

Additionally, you can auto-complete everything.

> It makes the APIs look like Java APIs more than they jQuery ones.

With jQuery, you often have those "options" objects which force you to check the documentation even if your editor is somewhat jQuery aware.

With Dart, you can just use named arguments. It's also clearer what the default values are. Of course things are also a lot easier if the machine can tell what you're trying to do.

> more like a C# collection of libraries

Well, that's the whole point. If you put type annotations at the API boundaries, those annotations can be used for documentation (fully cross-referenced), call-tips, auto-completion, type inference, and basic sanity checks.

This gets rid of lots of friction. Even if your own code doesn't include any types, the editor will be able to tell what's going on in many cases.

E.g. it knows that `1 / 3` results in a `double`, which has a `toStringAsFixed` method, which returns a `String`, which has a `length` getter, which returns an `int`.

So, if you accidentally write "lenght", the editor will tell you about your mistake right away. Well, you won't even make that typo in first place, because you'll just auto-complete that word.

Furthermore, if you store the value of `length` in a `var`, the editor will remember that it's actually an `int` and it will then notify you whenever you're doing something weird with it.

All of that works just because the libraries you're using are annotated.


The help of an IDE restricts the use of the language. It's the same for the TypeScript variant. If you say "you need a Visual Studio" or the like to use it comfortably, you're restricting the use-cases of the language.

I forgot to give the example of using "Enum-like" types instead of boolean parameters, because boolean parameters don't give enough information, so then you might need to pass something like MyClass.MYVALUE to a parameter rather than true or false.

So yes, there's much to like and dislike. Needless to say, there are those that need more type features from the language and toolset than it already offers, even if it's kind of hard because to come up with more if some of it needs to go into compiling down to JavaScript.

With more type features they would expect to have more features like real Enums or what-have-you.

Even "var" declaration starts to look awkward in a language where types are available. So things like "for (int i = 0; i < 10; i++) {}" are more natural than "for (var i = 0; i < 10; i++)". And that's only the tip of the iceberg.

When you start declaring things like "listenToMouseEvent(MouseEvent e, () {})" when using some event API, that's when it gets uglier still.

But yes, to each his own. JavaScript is still the leader in many ways, including some basic performance despite not the extra type declarations. They have really extracted nearly all of the performance allowed from JavaScript it seems. So performance alone is not what will differentiate these other languages from JavaScript.


Ruby is said to be useful for text processing and such. In Japan they had a need for the language to deal with text files specified in a Japanese codeset. Some of the flexibility to support different codesets cost Ruby a little. For Ruby 1.9 and 2.0, Matz took a while in the transition to "Unicode" support in order to keep some flexibility, even though many people preferred the old way of UTF8 and so on.

Ruby is best when it's used for the things it was meant for, but that hasn't kept people from trying to use it for more stuff. That's how Ruby found a good use in servicing web apps, first with CGI and then with dedicated instances in Rails and the like.

Now with Dart I understand that people demand languages be architected in different ways to extract more performance from them. Dart doesn't have "eval", for example. Whereas Ruby and Javascript do.

The question though is one of a divide, between the people who would never use Ruby or JavaScript and those who do use and love those languages that come with a lot of flexibility from the core. Python is like Ruby and JavaScript, even if the Python syntax could be borrowed for different languages that are more restricted in what they offer.


I don't see the point with eval. Every lisp has a eval, and most AOT Lisps are faster than ruby.

Not including eval seems to be a "discipline and bondage" fetish of language designers.

Yes, you can write pretty awful code with eval. But it allows metaprogramming aswell. I'd like to judge if something is awful or awesome.


With eval language designers might have a delayed execution that could make compile-time optimizations less straightforward. Part of the toolset could have to be present during deployment time to be able to handle eval which happens at runtime. And yes, security concerns could also play a hand.

In Dart the code declaration is taken very seriously in many ways, and avoiding eval buys them more compile-time, loading-time and perhaps runtime optimization opportunities. I find that more than the language designers themselves, it's the end-users or developers that ask for more "bondage and discipline" from their tools. People who come from Java and C++ backgrounds, for example. They just can't have enough compile-time stuff aided by an IDE.


Ruby is great in terms of allowing people to experiment with different algorithms pretty quickly. It's easy getting the code written and tested because the code tends to be so succinct, the standard library already includes a lot of shortcuts, it's synchronous, there's a lot of metaprogramming features readily available and the interpretation allows for quicker testing when you can get the basic syntax right after some experience without requiring the help of an IDE as most Ruby code is written in text editors.

Languages that demand IDEs tend to be more complicated in many ways. They can be faster, but also might demand more code obfuscation through more code that need to be written like types and longer names and importing of libraries and so on. My pet peeve is that I absolutely love Ruby, but it indeed is not meant for ultimate performance. On the other hand, languages like Dart might allow for some compromise if you can get stuff done with less power at your hands like less metaprogramming and fewer shortcuts... Except that Dart is trying to tackle asynchronous programming with the standard libraries which is itself quite complicated (Future what?)

Go and Dart are not themselves too tuned for performance yet, even though they tend to be very quick when compared to Ruby. They tend to solve different problems though.

Ruby has a couple of architects, Matz and SASADA for the VM. Go has a few. Dart has many, with some tending to the standard libraries.

Programming is unfortunately way too complicated. In my opinion, languages like Ruby are wonderful when you don't have a need to hide the source-code. On the other hand, languages like Go and Dart might be good when you do have a need to hide the source-code when deployment time comes.


Animations are fun. I recently created my first animated widget and it felt great. Going from "it works" to "it works and is animated" is a huge step. The animation really helps to tell the story of the switching in my widget. Think the animation of the Chrome tabs when you're switching them by dragging.


The main issue I have with "escaping from callback hell" is that it's a half-truth. Although I don't know much about how the Reactive Framework created by Microsoft works, I know they went well beyond the basics to try to make it all-encompassing coming closer to making it a full-truth.

Just transmitting data back and forth may play well to the strengths of your abstraction. But we have other uses with Timers that should also need such abstractions.

With Timers I have other needs like delaying the execution, resetting the delay countdown, stopping it before it executes it at all (like cancelling it), and finally with an Animation class I needed a way to finish executing a string of events in an instant in order to start a new animation. Also the Animation had other Animation versions at play that could need to be sped up before a new Animation started.

In .NET they seem to have a handy feature that waits the code to run before proceeding that comes into play with their .NET version of the Reactive Framework.

As far as I can tell, it's tough to really solve it. JavaScript doesn't have extra features like .NET does. We are more limited in what we can do. In Dart they have a version of this called Future that has been streamlined recently. As simple as it may seem to be, it comes with other related abstractions called Streams that altogether make it a bit daunting to escape from that hell only to land on the fire outright.


My own piece of feedback based on my experience. The slides were good. But like others, JIT is not all rosy. In V8 and Dart and .NET, code gets compiled to native code as soon as possible. I think that's the best case scenario in general. You then don't have to guess as much.

The author didn't mention method dispatching. I think it's an issue for many languages. In Dart, they tried to optimize it by the specification by mostly eliminating the need to change methods at runtime. In Ruby I watched a video by one of the core Ruby developers and he said that in Ruby method dispatching can be very complicated requiring up to 20 steps to resolve them.

As important as getting the best performance out of programs is to get the programs created in the first place. That's why I'm against shying away from larger codebases. I'm in favor of OO programming exactly because I think getting things done comes first, even if that could complicate the implementation of the toolset. And OO is all about layers of abstractions that bring more performance costs with them.

That said, I absolutely abhor type annotations. They make code hideous and decrease the opportunities for experimentations. Instead of reading a + b = c algorithms, you may need to parse A a + B b = C c source code.

In Dart we have Optional Types. But the core developers are fond of type annotations, so most samples they post come with them. I take relief in being able to omit type annotations while experimenting, researching and ultimately prototyping. Although in a way I feel like a rebel in the community for this disregard. Thankfully there is this chance to share a community with them.

Reading the part that you don't like adding heuristics to help programs to go faster reminded of adding types to them even if they are mostly disregarded as in Dart.

Then again, not all "dynamic languages" are the same. Some are truly dynamic with eval and runtime method changes. Others, not so much. Sometimes the tradeoffs allow for other kinds of gains that could come into play like when deploying. So there is a lot more to it than just getting the algorithms correct.


Trying to guess how Python works is quite hard if you're used to Ruby and other languages closer to Java.

As I don't know much Python myself, it's hard to tell where Python fails the "everything is an Object" check. But in Python some legacy calls were more procedural than OO, like "len(o)" rather than "o.len". I think eventually Python got to support both approaches.

I think Ruby is all objects even in its C abstractions. In Ruby, people create classes and so on in the RubyC abstractions that are visible to the Ruby language too. Not sure how Python does those.

I know Python has reference counting for Garbage Collection, so there are differences to their approaches in that regard and more.

Like Guido Van Rossum said, from 10,000 feet both Ruby and Python are more alike than different. He was saying that people should appreciate them more even if they belong to the community of the other one. That the real enemy is languages like Java that switch around the priority by making code that compilers prefer rather than programmers prefer.

I think Python has a Functions legacy that could not be as OO as they would be in Ruby.

Right now I'm more "in love" with Dart than with Ruby. Ruby was my first real love though.


Just as note: I don't really would call "len(o)" a "legacy call", as in "something it's here just for backward compatibility, but it's ugly and please don't use it".

It's more "the good way to do it" :D

len() is a perfect example of the duck typing and the "protocol-based" philosophy of python: its implementation it's something like

    def len(object):
        return object.__len__()
as in "just return the result of invoking the object method called __len__".

this lets you just call len() on every "len-able" object. They can be list, dict, custom objects... instead of the need to, I don't know, implements an explicit interface, or define a "getLength()", "size()", "length()", "length" (just an attribute, not a function to call), you can just define a "magic" (as in "normally you don't need to call this directly") method called __len__.

you can create your "not really a container, but it has a length!" object as something like

    >>> class C:
    ...     def __len__(self):
    ...         return 42
    ...
    >>> len(C())
    42

As indirect effect, it enables you to go on the functional-style approach... a simple

   map(len, list_of_lists)
it's more readable than

   map(lambda l: l.__len__(), list_of_lists)
(probably [len(l) for l in list_of_lists] it's more readable, but bear with me...)

I'm not really sure about the "ruby C abstractions": do you refer to the use of "object-like" structs used in the C sources of the "ruby MRI" implementation of "ruby-the-language"?

regarding the GC... I don't know, but why is the kind of the GC used by an implementation of the language (or the complete lack of a GC) relevant to the "everything is an object"?

just to be clear, I don't dislike ruby :) it's just that I don't find the "everything is an object" a way to discriminate between ruby and python.


You see, you wrote a bunch about how len is so cool in Python. But in the face of dynamic typing and polymorphism I didn't expect it to be any different really. Languages like Go that are statically typed make more of an issue about interfaces. Even in Dart they dropped explicit Interface usage in favor of implicit interfaces, considering that Dart is more explicit about matters than Ruby is.

Switching those function calls around reminds me of Delphi. When I first learned about Python, those calls reminded me of Delphi which I had used more. But once I learned Java, my frame of mind went from function(object) to object.function. With Ruby I found it quite intuitive. Now all languages work better if they approach things the way Java and Ruby do because of familiarity. That's why I like Dart for what it's worth.

Regarding C extensions of Ruby, they are like OO in C. Not sure how Python does it by default. But in Ruby all C extensions have a OO flavor. The first major book about Ruby writes about them: http://www.ruby-doc.org/docs/ProgrammingRuby/html/ext_ruby.h...

I think if you're counting references in the GC perhaps your C extensions are not very OO yet. In Ruby as in Java, the GC is an abstraction over reference counting. I think reference counting is often said to lead to more predictable performance at the cost of increasing the maintenance burden.

So again, not sure where Python is not "Objects all the way down." But Ruby has had the OO philosophy from early on. I think the Ruby OO approach started with the OO of the C extensions and went from there. Unlike Python that had a stronger procedural influence. The gap has closed since, but in Python a class is not written like this yet:

  class InRuby
  def aMethod
  end
  end

  class InDart {
  aMethod() {}
  }


I don't get the last part...

in python a class is written as

    class InPython:
       def aMethod(self):
           pass
but... what I'm missing? I can't follow the reasoning...

regarding the C extensions... I didn't really needed to write one, but from http://docs.python.org/3/extending/extending.html#a-simple-e... I see

    static PyObject * 
    spam_system(PyObject *self, PyObject *args)
    ...
so I assume also on C level the python objects are mapped on some structs in OO fashion...

I honestly have no idea on how is (or if it has some meaning) to extend python in rpython on pypy, but in this case I assume there are some objects involved :D


Exactly. In Python you still pass "self" to the method. In Ruby and Dart it's not needed.

In Python I've seen Python users discourage the use of classes. I haven't seen the same distrust of classes in Ruby for instance. It's as though Python has unresolved OO issues. Python could take pride in being "multi-paradigm", whereas languages like Ruby and Dart could take pride in being more OO.

Regarding the C extensions of Ruby, I think the bottomline is that from int, to booleans, to null, to classes, everything is considered OO even in the C code. So common functions can be applied to them even from C, say like Polymorphism would in other languages. From the primitives on up everything is like a high level Ruby. As Python is more "multi-paradigm" perhaps some of its C extension features aren't as OO as Ruby's are.

Funny though that those C extensions that make Python and Ruby so popular end up making other implementations of those languages that target other runtimes incompatible as they don't have access to those C extensions. So even in that regard they are similar.

Say we can't find anywhere in Python where Objects don't exist. Then welcome on board of true OO. Now show OO some love and stop discouraging the using of classes. Maybe drop the "multi-paradigm" approach. I know though that like JavaScript, sometimes you have to live with the shortcomings of the programming language in its support of OO. So while JavaScript could be said to have Objects everywhere, and it truly does, writing classes in JavaScript is not a settled issue. That's why I like Dart instead:

  class A {
    var aList = ['a', 'aa'];
    get length => aList.length; 
  }
  
  class B {
    var aList = ['b', 'bb', 'bbb'];
    get length => aList.length; 
  }
  
  class C extends A {
    var aList = ['c', 'cc', 'ccc', 'cccc'];
  }
  
  printIt(o) {
    print("${o.aList}: ${o.length}");
  }
  
  void main() {
    printIt(new A());
    printIt(new B());
    printIt(new C());
  }
Result of running it:

  [a, aa]: 2
  [b, bb, bbb]: 3
  [c, cc, ccc, cccc]: 4


>>Say we can't find anywhere in Python where Objects don't exist.

You're correct - we can't find a place in Python where Objects don't exist. Python and Ruby are exactly same in this.

>>Then welcome on board of true OO. Now show OO some love and stop discouraging the using of classes.

What do you mean by true OO?

It does not matter if you "love" objects or not. You can't write in python without OO. Every python module is an object, defs and vars - members of object. (Even classes and other modules are members of module object).


Or, instead of having the convention that objects with a length implement __len__, you could have the convention where they just implement len and you could just call obj.len.


In java the arrays objects expose a public int attribute called .length. The strings also expose a .length attribute, but it's a method. If, for some reason, you need to know how many elements are in enum, you need to call NameOfTheEnum.values().length. If you have a Collection (a Map, a List...), you need to call .size(). ...

Yeah. You are right about the fact that a possible "convention" would be to call .len, not .__len__ but you are forgetting 20+ years of backward compatibility.

I don't know when len() was introduced, and I'm not sure it's initial implementation was a simple "return object.__len__()" (or an equivalent...). What I know is that an explicit len function helped to hide the eventually different implementation details, and allowed the developers of the containers go crazy with attributes.

Moreover, with a len(obj) function and a obj.len() "public" method, you have two ways to do it.


I'm not sure why Python has to be backwards compatible with Java, given that Python is a totally different language released four years before Java.


I have quite a bit of Ruby for the server-side. But on the client-side I've been using Dart instead.

While Dart could be good for the server-side too, as it's VM will be as fast as any other dynamic language VM out there and the language is still quite cool, on the server-side we get to choose the tools more freely so there are many options.

Then again, why would people use Dart or Ruby on the server-side if they could use Go instead?

Go and languages like it are more lower level and sometimes more demanding, making mixing and matching while programming harder.

Mixing and matching is a way of programming for today rather than for the future. Say, dealing with the issues as they present themselves rather than trying to go around them. Say, dealing with the UI as they are popular rather than doing things in an unusual way while trying to guess the future.

I really liked watching an Intel guy say that if your approach to parallelism isn't about sharing the load to over a hundred threads, then forget about guessing the future.

For now as in the past, people have been successfully using threads for doing what they were originally meant for as Guido Van Rossum explained in a recent video. Threads were meant for concurrent I/O work. Now people want to push them to doing more parallelism. Not sure how we are going to get there.

Because like supporting many GUI front-ends has taught us, getting the most out of GUI often means that you need to target them on a one-to-one basis. Creating programs that support 1 thread or 100 threads from the same codebase will be quite a challenge going forward. Because if you want most performance from just 1 thread, it could be that the program needed to be written one way. Whereas to make it better for 100+ threads, it could need to be written a different way.

So, why would people write Ruby? Because it works. The Internet is unreliable anyways. Depending on a central server is too all-eggs-in-the-same-basket for the Internet.

Also Ruby is getting more stable. Depending on new tech can lead you to unstable nightmares.

If you were worried about bigger codebases and still wanted a language like Ruby, I'd first recommend Dart than Go. But for its current stability concerns. It will hit 1.0 soon though.


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

Search: