Links ? Pointers ?
[1/14] from: gchillemi::aliceposta::it at: 23-Aug-2009 12:00
Hello, I whish to ask a question to REBOL professional developers:
If we have:
A: [1 2 3]
B: C: :A
B and C would share the same list of A
If we set A
A: ["something"]
B and C would point to the list [1 2 3] and A to ["something"]
I am thinking about introducing a new notation for indirect links. Look at
this:
A: [1 2 3]
B: C: ::A ;(please notice the double colon)
B and C now would have a link to whatever A is pointing to.
If we change A
A: ["something" 1 2 3]
Then
PROBE B
and
PROBE C
should return ["something" 1 2 3]
It would be usefull for objects. When you create a new object you should be
able to link values/functions/lists to the previous object or copy them.
What about this ?
Giuseppe Chillemi
[2/14] from: carl:cybercraft at: 25-Aug-2009 12:41
Hi Giuseppe,
On Sunday, 23-August-2009 at 12:00:52 Giuseppe Chillemi wrote,
>I am thinking about introducing a new notation for indirect links. Look at
>this:
<<quoted lines omitted: 8>>
>PROBE C
>should return ["something" 1 2 3]
To achieve that currently, I'd do something like this...
>> a: [1 2 3]
== [1 2 3]
>> b: c: :A
== [1 2 3]
>> probe a
[1 2 3]
== [1 2 3]
>> probe b
[1 2 3]
== [1 2 3]
>> insert a "something"
== [1 2 3]
>> probe a
["something" 1 2 3]
== ["something" 1 2 3]
>> probe b
["something" 1 2 3]
== ["something" 1 2 3]
Is this not enough?
-- Carl Read.
[3/14] from: semseddinm:bircom at: 25-Aug-2009 9:23
> Hello, I whish to ask a question to REBOL professional developers:
> If we have:
<<quoted lines omitted: 4>>
> A: ["something"]
> B and C would point to the list [1 2 3] and A to ["something"]
This is because you created a new variable, not changed value(s) of A.
If you use insert/replace/remove/clear and other series functions then
A, B and C will point to the same variable.
[4/14] from: izkata:gma:il at: 25-Aug-2009 2:09
He's talking about the possibility of multiple variables pointing at
an immutable value:
>> X: make object! [Name: {Spock}]
>> A: B: :X
Then, say, changing the object entirely:
>> X: make object! [Species: {Human}]
and having A and B now also point to the new object.
Here's a way to simulate it:
>> X: reduce [make object! [Name: {Spock}]]
>> A: B: X
>> X/1: make object! [Species: {Human}]
Now, A/1 and B/1 also point at the new object.
2009/8/25 Semseddin Moldibi [ Bircom ] <semseddinm-bircom.com>:
>>
>> Hello, I whish to ask a question to REBOL professional developers:
<<quoted lines omitted: 17>>
> To unsubscribe from the list, just send an email to
> lists at rebol.com with unsubscribe as the subject.
--
=E5=A5=8F=E3=81=A7=E3=81=A6=E5=A4=A2
[5/14] from: ryan:practicalproductivity at: 25-Aug-2009 9:08
A: [1 2 3]B: C: does [A]
Personally I would rather not see real pointers.
--Ryan
PracticalProductivity.com
707-367-9230
On Tue, Aug 25, 2009 at 12:09 AM, Izkata <izkata-gmail.com> wrote:
[6/14] from: gchillemi:aliceposta:it at: 26-Aug-2009 20:02
> He's talking about the possibility of multiple variables
> pointing at an immutable value:
>
> >> X: make object! [Name: {Spock}]
> >> A: B: :X
You are right !
> Then, say, changing the object entirely:
> >> X: make object! [Species: {Human}]
> and having A and B now also point to the new object.
You have interpreted correctly my message.
> Here's a way to simulate it:
> >> X: reduce [make object! [Name: {Spock}]]
> >> A: B: X
> >> X/1: make object! [Species: {Human}]
> Now, A/1 and B/1 also point at the new object.
I whish a more direct way able to be able to link to a function and have
many object point to that function and reuse the code.
Giuseppe Chillemi
[7/14] from: carl:cybercraft at: 27-Aug-2009 17:53
On Wednesday, 26-August-2009 at 20:02:39 Giuseppe Chillemi wrote,
>> He's talking about the possibility of multiple variables
>> pointing at an immutable value:
<<quoted lines omitted: 13>>
>I whish a more direct way able to be able to link to a function and have
>many object point to that function and reuse the code.
Ok. Try ALIAS...
>> alias 'x "aa"
== aa
>> alias 'x "bb"
== bb
>> x: make object! [name: "Spock"]
>> probe x
make object! [
name: "Spock"
]
>> probe aa
make object! [
name: "Spock"
]
>> probe bb
make object! [
name: "Spock"
]
>> aa: make object! [species: "human"]
>> probe x
make object! [
species: "human"
]
>> probe bb
make object! [
species: "human"
]
>> probe aa
make object! [
species: "human"
]
ALIAS only works if the words haven't already been used though. So this doesn't work...
>> alias 'bb "cc"
** Script Error: Alias word is already in use: cc
** Near: alias 'bb "cc"
-- Carl Read.
[8/14] from: ryan:practicalproductivity at: 27-Aug-2009 9:27
Interesting! And, I thought *alias* was a lame function this whole time. But
one slight problem I have is that I can't actually figure out how this is
useful yet. Can anyone offer any pointers? : )
--Ryan
PracticalProductivity.com
707-367-9230
On Wed, Aug 26, 2009 at 10:53 PM, Carl Read <carl-cybercraft.co.nz> wrote:
[9/14] from: moliad:gm:ail at: 27-Aug-2009 22:00
there is one feature people often forget about rebol.....
it has NO syntax.
how do you represent/access a variable... hum...
x: "some value"
print x
how do you represent an object.... hum...
x: context [v: "some value"]
print x
how do you represent a function? ... hum
x: func [][ "some value"]
print x
hum.... see any constant?
however you define x... in any kind of data... you always USE it the
same way... some types just have more accessors... like objects which
have path access.
now you realize that the function and the "variable" both print the
same thing. just the string.
this is your secret indirect reference weapon!
you can always (almost) replace a value with a function and let the
function do some "special trick" ;-)
here, what you do is let the function point to some other value....
so if your code needed to do:
a: b: "some value"
you can ask function to act as a go between. the nice thing is that
most of your code won't have to change because REBOL has so little
syntax, only the assignment part will have to be updated... which is
usually much more confined a task than access to a value everywhere in
your app.
functions create a context, and that context persists for each call..
so a function actually can store values, here we use a block without
copying it at each eval... what some think is a limitation actually
now is shown as the feature it is. :-)
so let's say this is what your app should be:
person: context [
uid: 666
name: "me"
]
employee: context [
uid: user/uid
title: "Workoholic"
]
managers: [
ceo: employee/uid
]
now as you know, changing the uid in person won't be reflected in
employe or managers... so you're screwed!
----
Look at this modified version using function trick:
person: context [
uid: func [/set value][data: [#[none]] either set [data/1: value][data/1]]
name: "me"
]
employee: context [
uid: get in person 'uid
title: "Workoholic"
]
managers: context [
ceo: get in employee 'uid
]
>> person/uid/set 222
== 222
>> managers/ceo
== 222
>>
this is one way to use the function hack, but there are many others,
and they depend on the application itself.
there are a few little details when using the hack, but usually, its
pretty invisible.
Hope this helps :-)
-MAx
[10/14] from: tim-johnsons:web at: 27-Aug-2009 18:28
* Maxim Olivier-Adlhoch <moliad-gmail.com> [090827 18:07]:
> so let's say this is what your app should be:
>
> person: context [
> uid: 666
> name: "me"
> ]
>
Hi Maxim: See employee/uid below:
> employee: context [
> uid: user/uid
> title: "Workoholic"
> ]
Should that be person/uid ?
thanks
tj
> managers: [
> ceo: employee/uid
<<quoted lines omitted: 28>>
> To unsubscribe from the list, just send an email to
> lists at rebol.com with unsubscribe as the subject.
--
Tim
tim-johnsons-web.com
http://www.akwebsoft.com
[11/14] from: moliad:gm:ail at: 31-Aug-2009 2:49
Hi tim,
I did this on purpose, to show that they really are the same
reference. they both point to the same function which stores the same
value.
actually, all three objects contain the exact same function, so I
could set any of the three and any other would reflect the same value.
:-)
-MAx
On Thu, Aug 27, 2009 at 10:28 PM, Tim Johnson<tim-johnsons-web.com> wrote:
[12/14] from: gchillemi:aliceposta:it at: 3-Sep-2009 11:38
> person: context [
> uid: func [/set value][data: [#[none]] either set
> [data/1: value][data/1]]
> name: "me"
> ]
.....
> >> person/uid/set 222
> == 222
<<quoted lines omitted: 5>>
> there are a few little details when using the hack, but
> usually, its pretty invisible.
Hello Maxim, I have read your interesting post but I want the details. How
it works ? What happens underneat (at interpeter and structure details) when
you read the value of UID using another object like "managers/ceo" ?
Also, I whis to know the notes you have omitted about this approach and
eventually which other approach exists...
There are a lot of things I still have to know about objects.
Giuseppe Chillemi
[13/14] from: moliad:g:mail at: 14-Sep-2009 16:56
Hi Giuseppe,
Sorry I didn't check the ML for a few days and yours slipped in the cracks!
Here is a long and verbose explanation of most of what happens. If
something isn't clear, ask a precise question and I'll do my best to
explain it further.
so here we go... saddle-in, this is going to be a big ride into the
depths of some REBOL Guru level secrets. ;-)
I'll start by reposting the original code snippet as a reference:
person: context [
uid: func [/set value][data: [#[none]] either set [data/1: value][data/1]]
name: "me"
]
....
>> person/uid/set 222
== 222
>> managers/ceo
== 222
about functions as values
------------------------------------
Basically, all rebol datatypes are evaluated when they are encountered
by the interpreter. because functions require no more syntax than a
normal variable, they can be silently "slipped-in" as if they WHERE a
simple variable (cause in fact they are! :-).
The 'UID function, when created by the 'FUNC function creates a
context for itself. This context persists for as long as the function
exists.
If you notice the following:
data: [#[none]]
I assign a block! to 'DATA (I **DON'T** copy it at each function
evaluation). This block is actually part of the 'UID function's
context when the function is created. So it persists throughout that
function's existence... This means every time 'UID is evaluated, 'DATA
really is the same block, every time.
When I simply ask for the value of 'UID (person/uid), the function is
evaluated as normal, and it returns the first data of the persistent
block.
When I use the function's /SET refinement, I simply stores a new value
into this persistent block:
data/1: value
As a side note, remember that you can use blocks as indirections, a
bit like double referencing in C. Its a bit like saying get the first
value pointed to by the block pointed to by 'DATA. (I prefer to use
the term "refers" and "contains" respectively though).
About sharing functions across objects:
--------------------------------------------------------
Normally, when you make objects and use another object as the basis,
all of the functions are copied to the new object bound and bound to
it. This means that any words which are present in the body of the
function will now refer to those found in that object, or to those in
the arguments of the function. For example, if I had done this:
employee: make person [
title: "Workaholic"
]
And tried the function trick, the 'UID function inherited from 'PERSON
would not be shared because 'EMPLOYEE would contain a New &
independent copy of the 'UID function with its own persistent function
context.
The trick is to tell 'MAKE, what we we explicitly want the 'UID to be:
('CONTEXT is a mezzanine function which simply does: make object!)
employee: context [
uid: get in person 'uid
title: "Workaholic"
]
Here you see that we tell 'EMPLOYEE to use the exact same function as
the one in person. We 'GET it from the other object, and 'MAKE will
assign it to the new object, at the location referred to by word 'UID
in this new object.
It won't be bound to the new 'EMPLOYEE object, and 'UID will actually
be the same function as person/uid, NOT a copy of it.
This is a VERY powerful feature of REBOL.
From this point on, employee/uid and person/uid, being the same
function, really share the same function context, so will set and get
the same value.
Function hack level 2
-----------------------------
You said you wanted other examples of the function trick... Here we'll
go Fubar weird!!!
Lets refer to values of **another** object using 'SELF... :-)
;------------------------ the code -------------------------
person: context [
full-name: ["luke" "skywalker"]
first-name: func [/set val][either set [self/full-name/1:
val][self/full-name/1]]
last-name: func [/set val][either set [self/full-name/2:
val][self/full-name/2]]
]
employee: context [
first-name: get in person 'first-name
last-name: get in person 'last-name
full-name: func [][reduce [first-name last-name]]
]
;--------------------------------------------------------------
Within 'PERSON, we create a similar function-as-value trick, but this
time, we use 'SELF to refer to the context (object!) the function is
bound to, and then interact with another member of that object using
path notation.
'EMPLOYEE, if you recognize the pattern explained earlier, simply
borrows ('GETs) two of those functions-as-values and stores them in
its own context... but notice a HUGE detail. 'SELF in these
functions, still refers to the 'PERSON object, because the functions
are still bound to 'PERSON !!!
'FULL-NAME within 'EMPLOYEE, is bound normally since it is created by
'EMPLOYEE 's make. Meaning, it will evaluate whatever value is
referred to by the words 'FIRST-NAME and 'LAST-NAME within 'EMPLOYEE.
BUT!!! These, as we just explained, are values taken from the other
object, namely 'PERSON. So basically, you have an object calling
methods from another object, directly. This is far beyond the level
of control you can achieve with traditional inheritance and
polymorphism, IMHO.
You could go a step further and if you really wanted to go nuts with
this, you could change the person which is assigned to the
function-as-value referred by 'EMPLOYEE on the fly (but I won't go
there for risk of loosing you for now ;-)
All of this is AFAIK, a feature very few, if any, other languages
allow you to do so "legally", safely and with so much detail and
dynamic control.
here are a few lines of console code which play around with the above
level 2
function hack:
>> employee/full-name
== ["luke" "skywalker"]
>> employee/first-name/set "bill"
== "bill"
>> employee/full-name
== ["bill" "skywalker"]
>> person/full-name
== ["bill" "skywalker"]
>> same? person/full-name/1 employee/first-name
== true
>> same? person/first-name employee/first-name
== true
'SAME is a mezzanine function that only returns True if its the same
string, not just by its text content like equal?... it really is the
same string "pointer" in memory.
sweet isn't it ? :-D
about other uses of the function hack
-----------------------------------------------------
you might want to replace a value by an SQL statement
function-as-a-value which is executed every time a value is needed...
and if you set the value, it is inserted back directly... this way,
you are sure that your data is coherent.
In VID you can put functions instead of values for some facets...
example are colors, texts & effects which change every time the face
is shown... with a little tweak in the redraw :
example:
view layout [
button with [
texts: reduce [ does [to-string counter] does [random "ABCDE"]]
colors: reduce [ does [random white] does [random white]]
effects: reduce [
does [reduce ['gradient 0x1 color color - 75.75.75]]
does [reduce ['gradient 0x-1 color color - 75.75.75]]
]
]
feel [
redraw: func [face act pos /local state][
counter: counter + 1
if all [face/texts face/texts/2] [
face/text: either face/state [face/texts/2] [face/texts/1]
]
if face/edge [face/edge/effect: pick [ibevel bevel] face/state]
state: either not face/state [face/blinker] [true]
if face/colors [face/color: either face/state
[face/colors/2] [face/colors/1]]
if face/effects [face/effect: either face/state
[face/effects/2] [face/effects/1]]
]
]
]
here face/colors/2 is evaluated each time the face is drawn... so you
might want to put an sql statement which checks if an error occurred
on the db for example. whenever the face is refreshed it will be up
to date... which is pretty useful.
the view face is not a normal object so most of the primitive facets
(like color) will not respond if they are set to functions because the
view engine actually uses the values directly.
as an example if you put a function in face/text it will actually
display ?function? as the text...
but it should give you ideas on other uses... just the same.
-MAx
On Thu, Sep 3, 2009 at 5:38 AM, Giuseppe Chillemi
<gchillemi-aliceposta.it> wrote:
[14/14] from: moliad:gma:il at: 14-Sep-2009 17:02
oops.. just one little detail... 'SAME? isn't a mezz.. its a native...
-MAx
On Mon, Sep 14, 2009 at 4:56 PM, Maxim Olivier-Adlhoch <moliad-gmail.com> wrote:
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted