How to remove words from objects?
[1/13] from: luke:marmaladefoo at: 13-Jan-2004 10:21
Dear list
I'm trying to dynamically add and remove words from an
object. So far I can do the add words as follows:
>> obj: make object! [a: 1 b: 2]
>> probe obj
make object! [
a: 1
b: 2
]
>> obj: make obj [c: 3]
>> probe obj
make object! [
a: 1
b: 2
c: 3
]
>>
now I want to remove c from obj. How do I do that. I
know I could dynamically reconstruct it from scratch, but
that is not very elegant. There must be a better way to
get back to obj being:
make object! [a: 1 b: 2]
Any ideas?
Thanks
- Luke
__________________________________________
Various gadgets widgets, links and chat
http://www.marmaladefoo.com
__________________________________________<
[2/13] from: carl:cybercraft at: 24-Jan-2004 11:49
On 13-Jan-04, Luke wrote:
> Dear list
> I'm trying to dynamically add and remove words from an
<<quoted lines omitted: 19>>
> make object! [a: 1 b: 2]
> Any ideas?
The third value in an object is its block. ie...
>> obj: make object! [a: 1 b: 2 c: 3]
>> third obj
== [a: 1 b: 2 c: 3]
So, you could make an object from a copy of that block with the values
you don't want removed. The following for instance creates a new
object from the above one with the last two values removed...
>> obj2: make object! head clear back back tail copy third obj
>> probe obj
make object! [
a: 1
b: 2
c: 3
]
>> probe obj2
make object! [
a: 1
b: 2
]
Not sure how it'd work for more complex objects though.
--
Carl Read
[3/13] from: luca::truffarelli::it at: 13-Jan-2004 12:02
Not so beautifull but maybe work:
removefromobj: func [obj word] [
make object! head remove remove skip third obj add index? find first
obj word -1
]
rr: make object! [
a: 1
b: 2
c: 3
]
probe removefromobj rr 'b
[4/13] from: ingo:2b1 at: 13-Jan-2004 12:17
Hi Luke,
Luke wrote:
> Dear list
> I'm trying to dynamically add and remove words from an
<<quoted lines omitted: 15>>
>> obj: make object! remove/part find third obj to set-word! 'c 2
>> probe obj
make object! [
a: 1
b: 2
]
The main part in this expression is "third obj", which returns the object
as a block, like this:
>> third obj
== [a: 1 b: 2]
After that it boils down to removing the part that constructs the element
you want to remove, and use the new block to construct your object.
BUT BEWARE: you are always constructing NEW OBJECTS! This means, that
references still point to the old object, e.g.
>> obj: make object! [a: 1 b: 2]
>> a: []
== []
>> insert a obj
== []
>> probe a/1
make object! [
a: 1
b: 2
]
>> obj: make obj [c: 3]
>> probe obj
make object! [
a: 1
b: 2
c: 3
]
>> probe a/1
make object! [
a: 1
b: 2
]
; !!! a contains a reference to the old 'obj
So, it works well if you have only well defined references to your
objects, otherwise just use block!s for very dynamic entities. The
downside is that lookup in a block is not as fast as in an object.
I hope that helps,
Ingo
[5/13] from: joel:neely:fedex at: 13-Jan-2004 9:44
Hi, Luke,
Sorry.
Luke wrote:
> Dear list
>
> I'm trying to dynamically add and remove words from an
> object...
>
You can't.
> now I want to remove c from obj. How do I do that. I
> know I could dynamically reconstruct it from scratch, but
> that is not very elegant. There must be a better way to
> get back to obj being:
>
There's not.
-jn-
--
----------------------------------------------------------------------
Joel Neely joelDOTneelyATfedexDOTcom 901-263-4446
Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1
[6/13] from: greggirwin:mindspring at: 13-Jan-2004 10:50
Hi Luke,
You already got some solutions; I'll just add some comments.
L> I'm trying to dynamically add and remove words from an
L> object...I know I could dynamically reconstruct it from scratch,
L> but that is not very elegant. There must be a better way...
Not really. The issue lies in the fact that the context of an object
isn't dynamic; you can't add or remove things. The global context in
REBOL is the only special case of a dynamic context I believe.
You can get tricky and work around it, by including a block in your
object and using that as kind of a sub-context--because blocks are
resizable. I think Ladislav or Joel posted a dynamic object example
here at one time. I didn't find one on REBOL.org in a quick search,
maybe somebody submit one if they have it handy.
-- Gregg
[7/13] from: maximo:meteorstudios at: 13-Jan-2004 13:25
did you know you do not need a real object for object-like behaviour.
This is not the solution to everything, but well used, it can be as effective.
note that in the following, there is no context. and no 'self word. (you could define
it, but I'll leave that little part as an exam. Actually, one solution is included later
;-)
in short, just use a block which looks like the pairs of words and values you use to
define objects, but don't use set-word (word:) just simple words (word) .
blk: [
a 1
b 2
]
>> blk/a
== 1
>> blk/b
== 2
you can also add functions to it although its a little more complicated, but their usage
is as easy.
blk: compose [
a 1
b 2
pr (func [arg1][print [arg1 "...done!"]])
]
note the use of compose and the outer parenthesis surrounding the function definition
to use it though its as easy
>> blk/pr "hello world"
hello world ...done!
you can also assign values to the block like you would with objects:
blk/a: 44
when blocks are used for simple data storage, used properly, this trick makes blocks
behave almost identically like objects. With the difference that you can edit them much
more easily and that any references to them becomes safe.
adding a new thing to the object:
append blk [thing "thang"]
probe blk
[
a 1
b 2
pr (func [arg1][print [arg1 "...done!"]])
thing "thang"
]
but again, remember that there is no context, so functions do have limits unless you
really tear up your rebol mind and start doing run-time binding.. which is not the easier
task...
you can also add an argument to all functions called 'self, which then mimics the useage
of self. I this case, when calling a function in the block, just supply the block as
the first parameter of the function call...
with the tone of your mail, it seems that you are rather new to rebol.
if this is the case then Welcome!, and I hope this example is a true testatment to how
rebol can be used in many different ways.
Also note that rebol recycles most constructs you have learned, instead of forcing you
to learn completely new constructs for each different task. for example, arguments,
blocks of data, object specs code blocks, are all built up of BLOCK, which can be expressed
as rebol encounters them. in other languages, these are all built up of different (similar)
datatypes each allowing ONLY a (small?) subset of the capabilities which they all share.
HTH!
-MAx
---
You can either be part of the problem or part of the solution, but in the end, being
part of the problem is much more fun.
[8/13] from: luke:marmaladefoo at: 13-Jan-2004 18:25
Dear all
thanks everyone for your contributions!
I have in the meantime implemented my own approach
which works for me (similar to the ones suggested - see
below) using the "long way round" of reconstructing the
object. Its not very pretty (since it involves a "do" on a
dynamically built string) but it works for me, as do most of
your helpful suggestions.
I dont understand Gregg what you mean when you say
the context of an object isnt dynamic. It probably goes
beyond my current level of understanding of how REBOL
works.
But if so, then how does that explain why can I do this
(but not reverse the action):
;---create object
obj: make object [a: 1]
;---add a new word to the object
obj: make obj [b: 2]
> L> I'm trying to dynamically add and remove words from an
> L> object...I know I could dynamically reconstruct it from scratch,
<<quoted lines omitted: 7>>
> here at one time. I didn't find one on REBOL.org in a quick search,
> maybe somebody submit one if they have it handy.
This is the way I did it:
object-remove-word: func [object word /local obj-result obj-copy-string action] [
obj-copy-string: copy ""
obj-result: none
foreach w next first object [
if not (w = word) [
value: object/:w
append obj-copy-string rejoin [
" " :w ": " mold :value newline
]
]
]
action: rejoin ["make object! [" obj-copy-string "]" ]
obj-result: do action
:obj-result
]
All the best
- Luke
__________________________________________
Various gadgets widgets, links and chat
http://www.marmaladefoo.com
__________________________________________<
[9/13] from: ammon:addept:ws at: 13-Jan-2004 12:20
Luke to extend an object, MAKE the object...
>> obj: make object! [a: 'a]
>> obj: make obj [b: 'b]
>> probe obj
make object! [
a: 'a
b: 'b
]
HTH!
~~Ammon ;->
[10/13] from: joel:neely:fedex at: 13-Jan-2004 13:54
Hi, Luke,
Luke wrote:
> I dont understand Gregg what you mean when you say
> the context of an object isnt dynamic...
>
Once an object has been created, its "context" (namespace)
is set in concrete and cannot be changed (although the values
to which its words are set *can* be changed).
> But if so, then how does that explain why can I do this
> (but not reverse the action):
>
> ;---create object
> obj: make object [a: 1]
>
> ;---add a new word to the object
> obj: make obj [b: 2]
>
Because you are not adding a new word to *the*original* object,
but instead are creating a *new* object (based on the original)
which contains the new value. To see that this is not modifying
the original, just consider this:
>> obj: make object! [a: 1]
>> other: obj
>> obj: make obj [b: 2]
>> source obj
obj:
make object! [
a: 1
b: 2
]
>> source other
other:
make object! [
a: 1
]
So the original object is still around (referent of OTHER) but
now OBJ refers to a *new* object.
>>
>>You can get tricky and work around it, by including a block in your
>>object and using that as kind of a sub-context--because blocks are
>>resizable. I think Ladislav or Joel posted a dynamic object example
>>here at one time...
>>
If you want shared references to an object to all show the
effect of such "structural" changes, you can wrap the object
in another object (i.e. create an additional level of
indirection) which is the common referent:
>> wrapper: make object! [
[ inner: make object! [
[ a: 1
[ ]
[ ]
>> obj: wrapper
>> other: wrapper
>> source obj
obj:
make object! [
inner:
make object! [
a: 1
]
]
>> source other
other:
make object! [
inner:
make object! [
a: 1
]
]
>> obj/inner: make obj/inner [b: 2]
>> source obj
obj:
make object! [
inner:
make object! [
a: 1
b: 2
]
]
>> source other
other:
make object! [
inner:
make object! [
a: 1
b: 2
]
]
(Of course, the wrapper could be a block as well, but using
an object as a wrapper allows an easy way to put methods in
the wrapper that delegate to the inner object, so you can
hide the indirection from any client code.)
-jn-
--
Joel Neely com dot fedex at neely dot joel
I had proved the hypothesis with a lovely Gedankenexperiment,
but my brain was too small to contain it. -- Language Hat
[11/13] from: greggirwin:mindspring at: 13-Jan-2004 13:41
Hi Luke,
L> I dont understand Gregg what you mean when you say
L> the context of an object isnt dynamic. It probably goes
L> beyond my current level of understanding of how REBOL
L> works.
It just means that once you create an object, you can't add or remove
words from its context (words bound to the object); it's a fixed size.
You have to create a new object, which then has its own fixed size
context to add or remove words.
L> But if so, then how does that explain why can I do this
L> (but not reverse the action):
L> ;---create object
L> obj: make object [a: 1]
L> ;---add a new word to the object
L> obj: make obj [b: 2]
This works because you're making a new object. After it's made, all
you can do is change the values that its words refer to, you can't
unbind and remove the words themselves. To do that, you need to create
a new object that just doesn't contain them.
L> object-remove-word: func [object word /local ...
Does this work for you?
remove-word: func [object word] [
make object! head remove/part find third object to set-word! word 2
]
It's dense code, I know. Here's how the calls relate:
make object!
head
remove/part
find
third object
to set-word! word
2
It will fail with an error if the word doesn't exist in the object.
Just FYI.
-- Gregg
[12/13] from: g:santilli:tiscalinet:it at: 14-Jan-2004 9:50
Hi Gregg,
On Tuesday, January 13, 2004, 9:41:35 PM, you wrote:
GI> remove-word: func [object word] [
GI> make object! head remove/part find third object to set-word! word 2
GI> ]
BTW, on newer version of REBOL, if you're making the object from
the THIRD of another object, you should use CONSTRUCT. On earlier
versions of REBOL, where CONSTRUCT is not available, you'd either
have to write something like CONSTRUCT, or you need to keep in
mind that the above does not work on all objects. This is a
problematic example for the above:
>> print mold third context [a: 'a]
[a: a]
Regards,
Gabriele.
--
Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer
Amiga Group Italia sez. L'Aquila --- SOON: http://www.rebol.it/
[13/13] from: greggirwin:mindspring at: 14-Jan-2004 11:39
Hi Gabriele,
GS> BTW, on newer version of REBOL, if you're making the object from
GS> the THIRD of another object, you should use CONSTRUCT.
Excellent point!
-- Gregg
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted