News for hackers. Stuff that matters.
Re:Taking PHP Seriously by qwertyuiop924 on Thursday October 13, 2016 @08:34PM (#12705372)
That's because many dislike prototypical inheritance. It's perfectly usable.

As for misspelling field names, the same is true for variable names in both languages, and many things in many languages. Here it's more justified, as JS semantics mean that the language can't know your intent in this case: check your spelling.

Re:Taking PHP Seriously by codedokode on Thursday October 13, 2016 @10:15PM (#12705737)
> As for misspelling field names, the same is true for variable names in both languages, and many things in many languages.

No. This code causes an error in PHP:

    $name = 'John';
    echo $nmea; // error
    class A { public $name; }
    $a = new A;
    echo $a->nmea; // error
This code doesn't raise an error in JS:

    var a = { name: 'John'; };
    doSomething(a.nmea);  // no error
So with JS you learn about errors later and spend more time on debugging.
Re:Taking PHP Seriously by hiou on Thursday October 13, 2016 @10:56PM (#12705870)
Actually it throws an E_NOTICE. Something a fair amount of projects require you to turn off. You know what else throws an E_NOTICE?

    $a = notice_there_are_no_quotes;
    echo $a; // $a gets assigned the string 'notice_there_are_not_quotes'
This is super fun when you attempt to use a constant and misspell it.

    $b = MY_CONSTANTT;
    echo $b; // $b is now the string 'MY_CONSTANTT' instead of whatever the correct MY_CONSTANT was set to.
Which is why in both PHP and JavaScript if you really cared about what you were doing, both of those would be methods that throw errors if misspelled

    let a = new A();
    a.setName('John');
    doSomething(a.getNmea()); // Error

    $a = new A();
    $a->setName('John');
    doSomething($a->getNmea()); // Also error
Re:Taking PHP Seriously by codedokode on Friday October 14, 2016 @06:39AM (#12707200)
> Something a fair amount of projects require you to turn off. You know what else throws an E_NOTICE?

That is true only for low quality legacy code. I have always developed with all kinds of errors enabled and converted to exceptions (that means single E_NOTICE terminates the program with exception as it is done in Java).

Modern frameworks like Symfony 3 or Slim use the same approach. If you write a project using Symfony you won't miss a notice.

I think default PHP error handling system is wrong - there should be no warnings or notices, only exceptions. Sadly OOP was not very popular among PHP devs in the beginning.

Re:Taking PHP Seriously by arenaninja on Friday October 14, 2016 @08:18AM (#12707580)
IIRC PHP3 didn't even have objects

PHP4 introduced objects and is the language people shit on when they say PHP doesn't have real OOP

PHP5 introduced Java-like objects PHP5.3 introduced namespaces

Re:Taking PHP Seriously by OOPMan on Friday October 14, 2016 @09:16AM (#12707830)
I would imagine your doSomething JS function will fail and produce an error in the logging console because doSomething is probably not expecting to receive an undefined. Unless you've written it to handle that scenario and fail gracefully which is probably a good thing to do anyway.

Your whole example is silly. Stuff like this is why you write your PHP/JS/Python/Ruby code in a tool like WebStorm/PyCharm/RubyMine which does enough code analysis to realise you've made a typo and flag it.

Re:Taking PHP Seriously by jstimpfle on Thursday October 13, 2016 @09:08PM (#12705511)
In fact what's the difference between prototypical and conventional inheritances? I think python has exactly the inheritance model of JavaScript, and statically typed languages differ only in that they make the class=type, object=value distinction (so you can't dynamically change classes).
Re:Taking PHP Seriously by qwertyuiop924 on Thursday October 13, 2016 @09:35PM (#12705617)
It's not. In python, classes are entities like any other object. In JS, classes literally don't exist. Yes, even in ES6. I know there's a class keyword, but it doesn't actually create a class. What the class keyword creates is a constructor function which then initializes new objects with a set of properties, and also sets a prototype, when called with the new keyword.

JS objects don't have a superclass, they have a prototype. A prototype isn't a class: it's another object. When a method is called, or a variable is looked up on a JS object, JS scans up the prototype chain, all the way to Object.protype. But there's nothing special about these objects. If you wrote, say:

  var Person = function(){};
  Person.prototype = {name:"bill", addr:"foo"};
  var charlie = new Person();
  charlie.name = "charlie";
  charlie.addr = "baz";
  var NewPerson = function(){};
  NewPerson.prototype = charlie;
  var bill = new NewPerson();
This code is totally valid. bill's prototype chain looks like this:

  bill -> charlie (or NewPerson.prototype) -> Person.prototype -> ... -> Object.prototype
Welcome to prototypical inheritance.
Re:Taking PHP Seriously by deathanatos on Thursday October 13, 2016 @09:52PM (#12705660)
> A prototype isn't a class: it's another object. When a method is called, or a variable is looked up on a JS object, JS scans up the prototype chain, all the way to Object.protype.

A type in Python is also just another object. When a method is called, or a variable is looked up on an object, Python scans the MRO (effectively the same thing as the prototype chain, except it supports multiple inheritance too) all the way up to `object`.

Python's type system is very similar, if not nearly a superset (though probably not exactly), of JavaScript's. I struggle to see the real material differences in them.

Consider your example, translated:

  class Person:
    name = 'bill'
    addr = 'foo'

  class Charlie(Person):
    name = 'charlie'
    addr = 'baz'

  class NewPerson(Charlie):
    pass

  bill = NewPerson()
Re:Taking PHP Seriously by qwertyuiop924 on Thursday October 13, 2016 @10:12PM (#12705725)
That looks the same, but conceptually (and actually, code-wise), that's not what JS is doing. Here's what's actually happening, in psudo-python:

  class Person({name:"bill", addr:"foo"}):
    #there's no syntax for object literals in Python
    #such a thing doesn't even make sense: so I'm improvising.
    pass

  charlie = Person()
  charlie.name = "charlie"
  charlie.addr = "baz"

  class NewPerson(charlie):
    #note charlie is an object, not a class
    pass

  bill = NewPerson()
In JS, charlie isn't a class, charlie is an object: you can change all its properties and everything, just like any other object. It's not a class, because there aren't any.
Re:Taking PHP Seriously by OOPMan on Friday October 14, 2016 @09:18AM (#12707843)
I notice you conveniently ignored the meta-programming capabilities of Python which would allow your "nonsensical" improvisation to work just fine.

Brush up on your Python skills before talking rubbish.

Re:Taking PHP Seriously by qwertyuiop924 on Friday October 14, 2016 @12:42PM (#12709270)
Classless object literals actually don't make sense in the Python model. It seems like you're the one who needs to brush up.

In any case you're not actually providing any links or facts, so unless I dig through long articles on metaclasses in python, I can't verify anything you say. Please prove your point, or at least provide I link so I can verify.

Re:Taking PHP Seriously by OOPMan on Monday October 17, 2016 @12:17AM (#12722663)
Challenge accepted :-)

It should be interesting to see if I can actually abuse Python's meta-programming enough to make it work :-)

Re:Taking PHP Seriously by deathanatos on Friday October 14, 2016 @09:01PM (#12712150)
> In JS, charlie isn't a class, charlie is an object: you can change all its properties and everything, just like any other object. It's not a class, because there aren't any.

Right; this is actually why I like Python's way a bit better: it makes a more formal distinction between the two. In Python, Charlie is also an object, and you can change all its properties and everything, just like most¹ other objects.

Most of what you try to use to distinguish JS from Python applies just as well to Python. No, it isn't exactly the same, and I think the semantically equivalent code in Python will often contain more information than the JS. E.g., in my conversion of your JS, the class is an instance of `type`, whereas — as you correctly note — it's "just" an object in JS. It's not really though; in most JS that devs will write, the object is a type, but that distinction isn't explicit in the code. It's implicit in the dev's intentions, expressed only in the general sense that the code is being used.

e.g., if I saw, in JS,

  var Person = function(){};
  Person.prototype = {name:"bill", addr:"foo"};
  var charlie = new Person();
while it is true, technically, that `Person` is a function and `Person.prototype` is an object, the semantic meaning being expressed in this manner by the author of this setup is that `Person` is a type, and that charlie is an instance of that type. It's just explicit in Python. (To some degree, JS is aware of this fact too; `charlie instanceof Person` is `true`, after all.)

In a single-inheritance class in Python, during attribute lookup, Python will attempt to look the attribute up on the object's __dict__; if it doesn't exist, then it looks up the parent type (by looking at __class__) and then recurses, trying to look the attribute up there, and proceeding up the "chain".²

In JS, during attribute lookup, JS will attempt to look the attribute up on the object's internal list of attribute (I don't believe this is exposed like __dict__ in Python); if it doesn't exist, then it looks up the parent type (by looking at __proto__) and then recurses, trying to look the attribute up there, and proceeding up the "chain".

What material difference exists here?

¹objects in Python can forbid attributes from being set, or limit the available attributes. I'm not sure to what extend JS lets you do that. e.g., `object` in Python is very restrictive about allowing additional objects.

²I'm explicitly ignoring multiple inheritance here, so I'm vastly simplifying. Python will actually use the MRO for this procedure, but in the case of simple inheritance, that's equivalent to following __class__. I'm also ignoring __slots__ for simplicity.

Re:Taking PHP Seriously by chriswarbo on Friday October 14, 2016 @06:13AM (#12707109)
> A type in Python is also just another object.

Yes, but it's (roughly speaking) an instance of a "Class" class. In the "Person" example, the prototype of a "Person" object is another "Person" object (until the chain reaches an "Object", at least).

Re:Taking PHP Seriously by codedokode on Thursday October 13, 2016 @10:09PM (#12705716)
This code doesn't look good to me. What is the benefit of inheriting objects from objects instead of inheriting classes?

When we have distinct functions, classes and objects we can easily understand how they are supposed to be used: you can call a function, create an instance of a class, call a method of an object. With Javascript you cannot easily see whether you have a plain function or a constructor and how you should use it. And interpreter won't tell you anything if you forget to put a `new` keyword.

(And by the way why do you write 'var Person = function' instead of just 'function Person'? The latter is shorter and more readable)

Your code can easily cause a bug. Imagine Person's constructor looks like this:

    function Person() {
        this.friends = [];
    }
    ...
    var NewPerson = function() {};
    NewPerson.prototype = charlie;
Do you see the problem here? To fix the problem you have to rewrite the code using Object.create() and call parent constructor with Person.call(...).

I have written applications in Javascript and I think that Java-style classes are the best for readable and maintainable code. All these tricks with prototypes and dynamic objects (where you can add or patch properties in objects in runtime) might look good in short samples of code but they are only the source of bugs and cause waste of time to understand what the author meant in real world applications. Your code example proves that because adding a single field to a Person's constructor requires you to find and modify all of the objects inherited from it and this task is not easy too.

Re:Taking PHP Seriously by chriswarbo on Friday October 14, 2016 @06:37AM (#12707193)
It sounds like you're trying to write Javascript as if it were Java. I've worked with developers who did this (e.g. http://chriswarbo.net/blog/2014-03-12-trolled.html ) and I would advise that you instead try to write more idiomatic Javascript, or else use some kind of Java-to-Javascript compiler.

Your critique of Javascript is basically "it's not Java". I could make a similar critique of Java not being StandardML, but it would be about as meaningless:

When we have distinct structures, signatures and functors we can easily understand how they are supposed to be used: you can open a structure, create an implementation of a signature, apply a functor to a structure.

> (And by the way why do you write 'var Person = function' instead of just 'function Person'? The latter is shorter and more readable)

Personally, I prefer "var Person = function Person(...) {...}" since it makes the code more symmetric (the second "Person" makes stack traces more informative). The "function Person(...) {...}" style makes an artificial dinstinction between functions and everything else.

> All these tricks with prototypes and dynamic objects (where you can add or patch properties in objects in runtime) might look good in short samples of code but they are only the source of bugs and cause waste of time to understand what the author meant in real world applications.

Javascript is a dynamic language; there is no ahead-of-time compilation. Things can only be done at runtime, including adding properties to objects. If you mean that mutating values should be avoided, then I would emphatically agree. That's certainly not a Javascript-specific issue though, and Java is just as riddled with mutability as anything else.

I haven't had enough experience with prototypical inheritance to comment on it vs class-based inheritance; I've been burned enough by class-based inheritance that I tend to avoid inheritance in all forms (and OO too, these days).

Re:Taking PHP Seriously by codedokode on Friday October 14, 2016 @01:38PM (#12709745)
I am trying to write a code that is readable and maintainable instead of building complex abstractions. That is where Java classes fit perfectly (unless you are a beginner who had just read a book on patterns and tries to use every one).

And I am not only person who needs classes in JS: https://github.com/search?l=JavaScript&q=class&type=Reposito...

I do not see any benefit in prototypes. It just makes code more complicated and buggy. I would happily use them if I knew a way to do it while keeping code simple.

> When we have distinct structures, signatures and functors we can easily understand how they are supposed to be used

Yet Javascript has neither of those.

> If you mean that mutating values should be avoided

No, I am ok with mutable values.

Re:Taking PHP Seriously by chriswarbo on Friday October 14, 2016 @03:45PM (#12710573)
> I am trying to write a code that is readable and maintainable instead of building complex abstractions.

My point is that what's "readable and maintainable" depends on the language; especially on what facilities it provides, and to some extent community consensus (what's 'idiomatic').

Javascript's main facilities are first-class functions with lexical scope, lightweight key/value mappings (which it calls "objects") and prototypical inheritance between those objects.

Java's main facilities are classes with properties and methods; whilst it's recently gained first-class functions, most Java code has been written without them, and they'll always be in competition with classes+methods (e.g. look at all of the APIs which use single-method classes, like "Comparator").

These are very different, so what's readable/maintainable will differ in each. For example, Javascript's objects are so lightweight that it's idiomatic to write them inline exactly where they're needed, like 'foo({bar: function() { ... }, ...})'.

In idiomatic Java, such objects should be instances of a class, which should either be global or else implement a global interface. Since global class/interface declarations require standalone files, our declarations end up very far away from the use site; this prevents us accessing the use-site's scope and puts us under more pressure to make it descriptive, generic, reusable, etc.

> Yet Javascript has neither of those.

ES6 has a module system, Java has its "package" system. Trying to apply SML practices to either is a bad idea, just as trying to apply Java OO practices to JS is a bad idea, or trying to apply Lisp macro practices to C is a bad idea.

Re:Taking PHP Seriously by codedokode on Friday October 14, 2016 @05:11PM (#12711113)
> For example, Javascript's objects are so lightweight that it's idiomatic to write them inline exactly where they're needed, like 'foo({bar: function() { ... }, ...})'.

Idiomatic doesn't mean maintainable and scalable. Imagine you are working on a project in a team, not alone. How do you understand what kind of "lightweight" object you should pass to this function:

    function foo(data) { .. } 
When you have thousands of such functions you'll spend most time reading through their code to understand what type of argument they need. This means "idiomatic" javascript code works only when it is small in size. Once it gets larger you'll have to resort to old school non-idiomatic Java-like classes and a static typing system.

Regarding prototypal inheritance I don't understand how it is supposed to be used. Let's say we have constructors for objects User(name) and SuperUser(name, privileges). I understand if `SuperUser` is inherited from `User` (class-based ineritance), but I don't understand what is the meaning of SuperUser being inherited from some user charlie. Why `charlie` and not `john`? Why do I need an instance of common `User` to create a `SuperUser`? And as I haven't seen the explanation in above comments I guess you don't understand it too yet evangelize about it.

I think JS was supposed not to have any inheritance at all. The objects were supposed to be created with constructors and that is all. As an argument I can say that a helper method `Object.create()` that is required for object inheritance was only added in ES5 [1] and haven't existed in earlier versions. This is how you create objects from objects without classes and even without constructors:

    var person = { name: null, greet: function () { ... } };
    var john = Object.create(person, { name: 'John' });
    var charlie = Object.create(person, { name: 'Charlie' });
    var superCharlie = Object.create(charlie, { isSuperUser: true });
I also guess JS doesn't have classes because it was designed for writing simple form validation scripts and not large applications.

[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

Re:Taking PHP Seriously by qwertyuiop924 on Friday October 14, 2016 @08:27PM (#12712034)
>How do you understand what kind of "lightweight" object you should pass to this function

...and this is where well-documented interfaces come in.

>but I don't understand what is the meaning of SuperUser being inherited from some user charlie.

That was merely an example to express the difference: the idea is, instead of writing a class and doing things that way, objects are cloned from one another. If you want to create a user with special powers, you clone the user object (usually running a constructor function along the way) and give it whatever new functions you want. If you want to create more of these special users, you make them all have that one as a prototype. Typically, the prototype object is never actually used or altered from the defaults, as this would be confusing, and is given a constructor function to instantiate state. But it doesn't have to be.

>I think JS was supposed not to have any inheritance at all. The objects were supposed to be created with constructors and that is all.

Wrong. Object.create may be new, but prototypical inhertance is an important par of how the constructors you claim to be the way objects were meant to be created work. Function.prototype, the property which determines the prototype of objects created by a constructor, dates back to ES1.

>I also guess JS doesn't have classes because it was designed for writing simple form validation scripts and not large applications.I also guess JS doesn't have classes because it was designed for writing simple form validation scripts and not large applications.

Also complete nonsense. Prototypical inheritance was originally implemented in Self, a system developed my Sun Microsystems, and a descendant of Smalltalk-80, which certainly was designed for large applications. JS may have been built for writing simple for validation scripts, and it may be a deeply flawed language in some respects, but the fundamentals of the language, prototypical inheritance, true first-class functions, and lexical scoping, are all things that Eich got right. And given first class functions and lexical scope are still things that language designers have trouble getting right (I've got nothing against class-based OO, so I'm not including it here), it's even more remarkable that Eich did it properly in 1997.