Home   Archive   Permalink



Passing Around Objects

I am running into an issue with passing around objects and getting their data. It's probably something simple that I'm not understanding or overlooking, since I'm new to REBOL. I was wondering if someone could point me in the right direction please? I have written up a contrived and simplified example to demonstrate the problem ...
    
R E B O L []
    
getAccount: func [] [
     addr: make object! [
         country: 'USA'
     ]
        
     user: make object! [
         address: make addr [
             street: '123 Water St'
         ]
            
         name: string!
     ]
        
     user
]
    
printEmployee: func [info [block!]] [
     print info/1
     print info/2
]
    
account: getAccount
printEmployee ['Company ABC' account]
    
halt
    
----
    
I am trying to pass the account object to printEmployee and then print out its data, but instead it just prints out the the word account. Why is that, and how do I fix it?
    
Also, unrelated to this issue, but how do I post here without the double quotes getting converted?

posted by:   Brian       27-Sep-2016/14:49:45-7:00



Just to add some clarification... I realize you could probably fix this by defining printEmployee with two separate parameters instead of a block, but I would like to know how to pass the object in a block (if that is possible).

posted by:   Brian       27-Sep-2016/14:54:24-7:00



I hacked this together in about a minute. Something like this.
    
;; note the word self
;; see http://www.rebol.com/docs/core23/rebolcore-10.html#section-7
    
;; stub object
account: make object! [
    
     name: none
     street: none
     city: none
     state: none
     country: none
        
     say: func [
         {get the account}
     ][
         foreach word next first self [
             if not equal? Word 'say [
                 print rejoin [
                     word ":" tab get in self word
                 ]
             ]
         ]
     ]
]
    
;; first "instance" of yet another account prototype
    
a2323: make account [
    
     name: none
     addr: "123 Water St"
     city: "Nowhere"
     state: "OR"
     country: "USA"
    
]
    
>> a2323/say
name: none
street: none
city: Nowhere
state: OR
country:    USA
addr: 123 Water St
    
Do this at the console to see the innards.
    
» probe a2323
    
In the REBOL world, passing around would mean sending an object from one instance of REBOL to someone else's instance in a message (a file with a REBOL file).
    
    


posted by:   Time Series Lord       27-Sep-2016/19:30:49-7:00



Notice. In my account proto, I used
    
street: none
    
but in my account A2323, I goofed and used
    
addr: "123 Water St"
    
Probe and find out what happened!

posted by:   Time Series Lord       27-Sep-2016/19:33:10-7:00



Let us look at this a bit deeper.
    
Your Problem: "I am running into an issue with passing around objects and getting their data."
    
Make this one of your REBOL mantras:
    
The REBOL Virtual Computer (RVC) computes values to return results. A result is merely a value. The RVC always returns something (e.g., processed data, error, etc.)
    
1. You can restrict your function definitions to specific datatypes.
    
tweedledee: func [
O    [object!]
][
    
    ;; processing code
    ;; returned result, the word result is implied
    
]
    
tweedledum: func [
O    [object!]
][
    
    ;; processing code
    ;; returned result, the word result is implied
    
]
    
;; assuming already defined object
;; change the object named o with tweedledee
resdee: tweedledee o
    
;; change the result of the previous change with tweedledum
resdum: tweedledum resdee
    
There. You have "passed objects" Between functions.
    
But the major design question becomes, why use objects at all? If you had millions of records, what would get from having objects?
    
The purpose of OOP Is to encapsulate attribute data and expose an API through accessor functions. My above design does that, except, you, the coder can access the attribute data easily enough.
    
But if you're passing objects to functions, why bother with objects? If you don't have functions defined in objects, why bother with objects?
    
With REBOL objects, You can't do anything like this:
    
>> find a2323 "OR"
** Script Error: Invalid argument: OR
** Near: find a2323 "OR"
    
However, you could do that if a2323 is a block. Nor could you search millions of objects with ease. You can with nested blocks and recursive use of find.
    
See: http://www.rebol.org/ml-display-thread.r?m=rmlMCDS
    
Nor could you do a superfind SQL-ish like,
    
pseudo-code» find all accounts in oregon
    
Likely, Carl threw in objects to pander to the burgeoning Java world at the time. Objects are not needed for good design even though you find objects used in mezz functions as well as the result of layout, the VID parser/processor, the email header, the system object, etc.
    
For any kind of account app, anyone would be better off using encrypted dialects sent to REBOL instances and then use functions that update a record represented by a block in a block of accounts. You could even design an account protocol to send those encrypted messages over a secure tunnel of some kind.
    
see: http://www.rebol.com/docs/encryption.html
    
Decrypted:
    
[get personal details account A2323]
[add deposit $100 account A2323]
    
One way would be to use FFP and chain together your functions.
    
Return-Deposited Return-Account Return-Decrypted encrypted-dialect-message
    
You are invited to read my work. It exists for anyone looking to learn REBOL/Red
or see REBOL/Red in a new way.
    
The RVC, Red and REBOL
http://timeserieslord.github.io/red/
    
    
    
    
    
    
    
    


posted by:   Time Series Lord       27-Sep-2016/20:44:17-7:00



Data in a block is inactive / not applied.
To get to the value of data in a block,you have to follow one level of indirection, e.g.
    
A: make object! [b: 1]
C: [a]
F: func[d][ print get d/1]
F c
    


posted by:   Ingo       28-Sep-2016/0:12:44-7:00



Wow, awesome guys! Thank you for all your responses!
    
I'll be going through all your answers in more depth tonight :) ... but it's an interesting coincidence you mentioned encryption Time Series Lord. Inspired by the dialect thread the other day, I started working on a cryptography dialect last night. I just wanted to see if I could wrap my head around the concept, and this is where I started to run into the problem I posted about.
    
The user account stuff was just a contrived example for the purposes of explaining the problem easier. I am not tied to the concept of OOP either, the only reason I want to pass a object around is because I have a need to pass the "rsa-make-key" object to my dialect parser and this kept failing.
    
Anyway, cheers guys! Let me start reading ...

posted by:   Brian       28-Sep-2016/1:02:57-7:00



So, it looks like you guys are both saying I should re-write my code instead of passing the object in a block :)
    
The first example uses reflection, the other two pass the object to the function directly, instead of inside a block. So it doesn't sound like what I want is possible. That's fine, it's actually made me re-think my design, and I have come up with a simpler solution where I only pass in the value I need and rebuild the object in the function.
    
Thank you for your help everyone!

posted by:   Brian       28-Sep-2016/12:14:24-7:00