Does Rebol really have an equivalent for javascript prototype property?
Asked Answered
D

4

5

Gregogy has made a post about rebol and javascript here http://blog.revolucent.net/2009/05/javascript-rebol.html

But as I'm going deeper into comparing javascript and rebol, I can't see what's the equivalent of rebol for javascript prototype. Because extending an object instance from another one with make in rebol isn't exactly like javascript prototype property as js prototype allows to extend ALL instances at once.

So am I mistaken or is there an equivalent of the code below for rebol:

<html>
<head>
</head>

<body>
  <script>        
    function Person(firstName, lastName, sex) {
      this.firstName = firstName;
      this.lastName = lastName;      
      this.whoAreYou = function() {
        alert( "I've been built with Constructor and my name is " + this.firstName + " " + this.lastName);
      }
      this.WhatIsYourSex = function() {
        alert(this.sex);
      }
    };

    Person.prototype.sex = "Man";

  </script>

  <script>
    JaneDoe = new Person("Jane", "Doe");
    JaneDoe.whoAreYou();
    JaneDoe.WhatIsYourSex();
    alert("Are you sure?");
    JaneDoe.sex = "Woman";
    JaneDoe.WhatIsYourSex();
  </script>

</body>
</html>

Update: I don't care about syntactic sugar of course. Nothing prevents extension in R2 by just redefining an object. My question is not about extension of an object INSTANCE but about extension of ALL INSTANCES at once: that's what js prototype property allows.

So to reformulate my question: Can Rebol allow to also extend AUTOMATICALLY ALL INSTANCES of children by extending the parent class like javascript can whatever the syntax I don't care ?

For performance sure I see the difference between R2 and R3 for one instance but as for language functional feature I don't have automatic extension of all children objects which is a big burden as I'll have to manage them myself which will be quite slow since it's not done by the system itself. What if I want to create a framework like jquery which heavily relies on this kind of feature ? It would be a great hassle.

Disservice answered 24/11, 2010 at 22:14 Comment(3)
Comparing languages on syntax is rather ... silly. Ofcourse there will be similarities, especially if they're both functional languages with concepts taken from Self, Lisp and Scheme... Check out how much CoffeeScript looks like JavaScript or compare it with Groovy for that matter =PGilbertine
Who talks about comparing syntax ? It's about comparing capabilities of course. I don't care 1 cent about syntax.Disservice
I never made any such claim in my blog post, Rebol Tutorial, but I'm glad it ended up making you learn more about REBOL. Prototype languages can work in several different ways. REBOL is a prototype language because you make new objects based upon existing objects rather than class specifications.Mullah
P
7

Oldes is right, the JS-like prototyping is not present in REBOL by default. But you are free to create own functionality that suits your needs. Here is simple example that uses nested context for value sharing between multiple instances to simulate the JS prototyping:

creature: func [
    /prototype
        field [word!]
        value [any-type!]
    /local result proto
][
    proto: [
        context [
            static: context [
                vars: reduce [
                    'kind "Monkey"
                ]
                extend: func [
                    blk [block!]
                    field [word!]
                    value [any-type!]
                    /local pos
                ][
                    either pos: find/skip blk field 2 [
                        change/only next pos :value
                    ][
                        insert/only insert tail blk reduce field :value
                    ]
                    :value
                ]

                get: func [
                    field [word!]
                ][
                    all [
                        field: any [
                            select/skip this/instance field 2
                            select/skip vars field 2
                        ]
                        first field
                    ]
                ]

                set: func [
                    field [word!]
                    value [any-type!]
                ][

                    extend this/instance field :value
                ]

                prototype: func [
                    field [word!]
                    value [any-type!]
                ][
                    extend vars field :value
                ]

                who-are-you: does [
                    print ["Hello I'm" this/get 'kind this/get 'sex this/get 'first-name join this/get 'last-name "."]
                ]
            ]

            instance: reduce [
                'first-name none
                'last-name none
            ]

            ;exported "API"
            get: system/words/get in static 'get
            set: system/words/get in static 'set
            prototype: system/words/get in static 'prototype
            who-are-you: system/words/get in static 'who-are-you

            this: none
        ]
    ]
    unless object? proto/1 [result: reduce proto append clear proto result] 

    if prototype [proto/1/prototype field :value]

    result: make proto/1 []
    result/this: result
]

creature/prototype 'sex "male"


jane: make creature []
jane/set 'first-name "Jane"
jane/set 'last-name "Rebol"

john: make creature []
john/set 'first-name "John"
john/set 'last-name "Doe"

jane/who-are-you

jane/set 'sex "female"

jane/who-are-you

john/who-are-you

creature/prototype 'kind "Human"

jane/who-are-you
john/who-are-you
Petras answered 12/6, 2012 at 12:28 Comment(0)
C
6

REBOL does not have a equivalent.

An object in R3 is created using any other object as a prototype. But once, created, it is an independent entity. Changes to the object that was used as the prototype will not affect the newer object -- or vice versa.

Objects in REBOL 2, once created, cannot have new fields added to them; all you can really do is create a new object based on the old one, but with new fields. That can be annoying, as it may break references to the old object.

REBOL 3 is much better in that way. extend and append allow new fields to be added to any object.


This script may help a little: link text.

  • It compares an target object to a reference object, and adds any missing fields:
  • It is REBOL 2 code, so the target object gets replaced by a copy rather than extended
  • but it does recurse through any nested objects, so it can make complex nested changes in one pass
Circumlocution answered 25/11, 2010 at 7:35 Comment(3)
Sunanda I can't see real difference between R3 and R2 on that point except syntatic sugar. Nothing prevents extension in R2 by just redefining an object. My question is not about extension of an object INSTANCE but about extension of ALL INSTANCES at once: that's what js prototype property allows.Disservice
You'll see the difference if you have multiple references to the same object (eg it is stored as both blk1/3 and blk2/7). In REBOL 2 you'd have to replace them both. With REBOL 3, you can extend either reference. Try playing around and see.Circumlocution
For performance sure I see the difference but as for language functional feature I don't have automatic extension of all children objects which is a big burden as I'll have to manage them myself which will be quite slow since it's not done by the system itself.Disservice
D
3

Rebol Tutorial, your reactions contain too much of "I don't care", don't you think? And by the way, design wise - who on eart came with an idea of a class definition influencing live objects after class instantiation happened? :-)

So - did you actually do any measurements, to compare how slow it is to extend related objects in a loop? Your claim " ... will be quite slow" might show as unsubstantiated.

Let's do some measurements:

obj: context [a: 1] == make object! [ a: 1 ]

dt loop 1'000'000 [append blk copy obj] == 0:00:00.023372

length? blk == 1000000

dt [foreach obj blk [append obj [b: 2]]] == 0:00:02.677348

length? blk == 1000000

blk/1 == make object! [ a: 1 b: 2 ]

blk/2 == make object! [ a: 1 b: 2 ]

blk/1/a: 3 == 3

blk/1 == make object! [ a: 3 b: 2 ]

blk/2 == make object! [ a: 1 b: 2 ]

So, as you can see, I managed to extend 1 million of objects with custom fields in == 0:00:02.677348 time. I am on 4 years old machine. How many of objects your application have?

I know it's not what you probably want, as you have to build list of objects to extend, but it is a starter :-)

-pekr-

Derte answered 27/11, 2010 at 16:9 Comment(6)
Your example is contrieved. In real world you'll have a hierarchy of objects. Since Rebol won't manage this tree for you, that will be a huge burden for the developer. Not great for a language that is supposed to be easier than others. Also in other fields like just parsing rss feeds to build an aggregator, I found that rebol was too slow and I had to come back to php. So in real world I now fear that rebol is not robust enough except for gurus hacking it. But I'm not guru and many aren't either. If you want rebol to be easier it should be easier for complex task not for easy task.Disservice
Once again - claims like "too slow", and mention of "coming back to php" are untruthowrthy for me, especially when you don't provide description of problem at hand. When using a language, it is about using its natural facilities and adjusting your alghoritms to what it offers. Direct translation of 1:1 of the source code never works properly. Max has node based object system in Rebol, which can handle millions of nodes, fast enough to be used in real-life app. It is all about mindset used when creating particular solution, and you should re-adjust between the tools, or stay with - PHP, JS.Derte
This is the kind of problem one encounter with rebol #4298153 so when I will be using this extension stuff on my example I expect what I usually encounter with rebol : the wall :)Disservice
The only wall is in our imagination :-) If I have some time, I will try to look into the prototype stuff. But - I am not the most skilled reboller around, we will see ...Derte
I would like to see your RSS aggregator if you claim it was too slow. I think that the main problem is, that you probably try to write code in the way like in JS or PHP. I'm sure you could use REBOL way instead, like using PARSE. Again.. I would really like to see your code.Lira
@Petr I'll see if your imagination can break the wall ;)Disservice
L
1

I guess you will not like this from some reason:

person: context [
    firstName: secondName: none
    whoAreYou: does [print [firstName secondName]]
    WhatIsYourSex: does [print sex]
]
extend person 'sex "male"
JaneDoe: make person [firstName: "Jane" secondName: "Doe"]
JaneDoe/whoAreYou
JaneDoe/WhatIsYourSex
ask "Are you sure?"
JaneDoe/sex: "female"
JaneDoe/WhatIsYourSex

I must say, that I would not use code like this one in real as I don't see reason why I should mix data with functions. It's just a try to mimic your JS code.

But I guess, you have wrong example and you want to show this:

<script>
    JaneDoe = new Person("Jane", "Doe");
    DoeJane = new Person("Doe", "Jane");
    Person.prototype.sex = "Man";
    JaneDoe.WhatIsYourSex();
    DoeJane.WhatIsYourSex();
</script>

Than I must say, that in REBOL something like this is not supported, at least now.

Lira answered 30/11, 2010 at 18:22 Comment(7)
Your code doesn't reflect the same intent as my js code; the intent of my js code was to show that prototype in js allows to propagate changes to all instances at once whereas in rebol you cannot do so. To be more explicit with js prototype you can easily simulate class inheritance and create powerfull frameworks like jquery.Disservice
As you can see, I corrected your example to show what you wanted to show in second part of my answer. Your example was not propagating change to all instances. Also I think you can simulate propagation in REBOL, but it would require some work, for which i don't have time at this moment.Lira
Also what do you mean when you say: "with js prototype you can easily simulate class inheritance"? JS is ECMAScript and so it has class inheritance, so you don't have to simulate something, do you?Lira
And one more comment... you can make powerful frameworks even without class inheritance. Personally I don't like heavy class based projects as they are usually very difficult to read (as you must go thru all classes to find where some methods come from). But for sure, other people would like it, it's a metter of taste.Lira
Sure you can do almost anything without inheritance, even without instance, even without rebol, ... using just assembly : The problem is how quick and easy you can do this without having a headache or being the gurus of the language :)Disservice
I don't understand why you said "Your example was not propagating change to all instances." Sure it is by the very fundamental essence of js prototype behavior. js prototype is not about instance but indeed about class behavior though the term "class" is not used in js paradigm it does have the feature that a class have in other traditional languages.Disservice
"Your example was not propagating change to all instances." = in your example you don't have any instances when you do the change.. that's quite important difference... that's why I could give you exact functionality in REBOL.... and related the previous comment.. I'm using REBOL a lot of years everyday and I never missed what you want to show (as I'm not sure you want to do it actually). I'm sure I could find solution easily if I would need something real. And if I ever head a headache, it was when I had to examine where some deep methods comes from in AS code. And from alcohol:)Lira

© 2022 - 2024 — McMap. All rights reserved.