r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[Core] Discuss core issues

Joe
22-May-2006
[4594x3]
I am using this for message composition, templates, etc.. So imagine 
you have a template: "<html><head> title </head><body> body </body></html>" 
but with many more tags and then you have a large funtction emit-page 
that generates many tags and when you generate the page you want 
to make sure that you've generated all the tags and if you missed 
some then you get an error
I think the above explains the problem domain. Imagine pages with 
lots of tags and that you don't want to clutter the emit-page function 
with lots of template variables neither want to compose the function 
given that if is a normal function where you do have other normal 
local variables. I am looking for ideas on how to approach this
if is a normal function
 --> i meant "it is a typical function definition
Anton
22-May-2006
[4597]
So you want an expanding block of name value pairs to be checked 
by a function.

Something like: [title "Product X website" introduction "Product 
X is a new way to..." cost 25.90]
Joe
22-May-2006
[4598x4]
I want the easiest possible approach i.e. you create an html file 
and define the tags like in the example above template:
and then you collect with a function the list of tags that you've 
created and then in a function you go and define dynamically all 
those tags as variables i.e. title: func-title "xyz" ...
I want to use the power of bind and contexts to make sure this works
going to lunch. talk to u later thanks
Anton
22-May-2006
[4602x2]
Or wait... you want a context to keep all your template variables 
in:
	template: context [title: introduction: cost: none]
then unset all the variable in the template:
	unset bind next first template template

Your function references words in the template and receives an error 
for the first one which is unset.
	f: func [template][do bind [?? title] template]
	f template
	** Script Error: title has no value
	** Where: ??
	** Near: mold name: get name
but works fine when they have values:
	template/title: "hello"
	f template
	; ==> title: "hello"
That should give you some ideas.
Ladislav
22-May-2006
[4604]
how about an UNBIND function as follows:
Joe
22-May-2006
[4605x2]
what is the syntax of unbind ? is it costly to execute ? I would 
use it unbind the block of variables before creating the template
i imagine this could be a solution using the global context
Ladislav
22-May-2006
[4607x2]
just a moment, testing
unbind: func [
	{unbind words}
	[catch]
	words [word! block!]
	/local word result object
] [
	if word? words [words: reduce [words]]
	result: copy []
	unless parse words [
		any [set word word! (insert tail result to set-word! word)]
	] [throw make error! "unexpected data"]
	exclude result [self:]
	insert tail result none
	object: make object! result
	either find result first [self:] [first object] [
		exclude first object [self]
	] 
]

blk: [a b]
a: 1 b: 2
f: func [/local res][ 
	res: bind/copy unbind blk 'res 
	probe reduce res
]
f blk
Joe
22-May-2006
[4609]
I get script error: self has no value and I get the same error if 
I set a and b after bind in function f
Ladislav
22-May-2006
[4610x5]
show me your code, please
(the code producing the "self has no value" error)
Here my understanding would be that a and b are not
set in that context 
and the result is an error.

 - right, neither 'a nor 'b exists in the function context, therefore 
 they remained global
(or unbound, in my version of the function)
It looks, that we don't know what exactly you want to accomplish, 
and it is a bit hard to guess. Could you be more specific?
Joe
22-May-2006
[4615x5]
I am using linux and the clipboard doesn't worked so I typed the 
code
unbind: func [
        "unbind words"
        [catch]
        words [word! block!]
        /local word result object
][
        if word? words [words: reduce [words]]
        result: copy []
        unless parse words [

                any [set word word! (insert tail result to set-word! word)]
        ][ throw make error! "unexpected data" ]
        exclude: result [self:]
        insert tail result none
        object: make object! result
        either find result first [self:] [first object] [
                exclude first object [self]
        ]
]

blk: [a b]
a: 1 b: 2
f: func [/local res][
        res: bind/copy unbind blk 'res
        a: 1 b: 1
        probe reduce res
]
f blk
** Script Error: self has no value
** Where: f
** Near: self
>>
I get the same error when commenting a: 1 b: 1 line inside f
Ladislav, thank your help. I wanted to ask you about this via the 
mailing list and I did send the message earlier this morning but 
the mailing list is down. Please bear with me and I will provide 
the details. I think the solution you provided is exactly what I 
was looking for but I might be missing some detail. I am studying 
your code right now and will be more specific in a few minutes
Gregg
22-May-2006
[4620]
Could you write the steps of the problem domain in pseudo-code for 
us? i.e. forget about the implementation for the moment.
Joe
22-May-2006
[4621]
i am preparing the pseudo-code. just a few minutes
Ladislav
22-May-2006
[4622x2]
your code contains the following bug:

    exclude: result [self:]
the original line is

    exclude result [self:]
Joe
22-May-2006
[4624x6]
thanks. I will post real code because I think it explains the problem 
better
template:       to block!  "<html><head><title> title </title></head><body>tag1 
tag2 tag3</body></html>"


blk:            remove-each val load copy template [tag? val]    
?? blk ; == [title tag1 tag2 tag3]

tag3:           "this is a fake value, should not appear"

eval-template: func [
        /local res
][
        res:            copy ""
        title:          "hey"
        tag1:           "this is tag1^/"
        tag2:           "i am tag 2^/"
        ;tag3:          "might not be set^/"
        bind/copy       template 'res
        repend          res template
        res
]
sorry pls look at the next example
template:       to block!  "<html><head><title> title </title></head><body>tag1 
tag2 tag3</body></html>"


blk:            remove-each val load copy template [tag? val]    
?? blk ; == [title tag1 tag2 tag3]

tag3:           "this is a fake value, should not appear"

eval-template: func [
        /local res
][
        res:            copy ""
        title:          "hey"
        tag1:           "this is tag1^/"
        tag2:           "i am tag 2^/"
        ;tag3:          "might not be set^/"
        bind/copy       unbind blk 'res
        repend          res template
        res
]
The unbind function is very close to what I want. In the previous 
example if the function body does not set the variables a or b it 
prints [none none]. What I want is that if a variable in blk is not 
set then it throws an error
IPls let me know if this example is not clear. What I want is to 
catch the case where tag3 is not set and throw an error This is useful 
where the tags are set in a large function and there are many tags
Ladislav
22-May-2006
[4630]
Your EVAL-TEMPLATE function does not have 'TITLE as local variable. 
Do you want 'TITLE to be local or not?
Joe
22-May-2006
[4631x2]
I want title to be local without defining it in the spec. Eval template 
is a function that might be used for many different templates
IMy understanding is that if you bind a word to the local context 
then it's a local even if it's not defined in the spec but I probably 
have multiple misunderstanding (though I just read the Bindology 
Bible by Ladislav)
Ladislav
22-May-2006
[4633x3]
unfortunately that is not true, at least not in this REBOL version
local contexts are somewhat "static", i.e. they cannot be enlarged
(section 15)
Gregg
22-May-2006
[4636]
local without defining it in the spec
 -- I don't think that's a good way to think about modeling it.
Joe
22-May-2006
[4637]
I see. This is a major limitation. I see the rebol3 has a blog entry 
that "bind expands contexts" How could I approach this with the current 
rebol ?
Anton
22-May-2006
[4638]
No, that's right. Contexts cannot be extended with new words (at 
this time).  I would pass a context to your function with the template 
and all the words in it. This context will have to be built at the 
beginning.
Gregg
22-May-2006
[4639]
It's still not clear to me what the real goal is. i.e. where values 
come from and how eval-template may be reused without giving it some 
parameters to guide it.
Anton
22-May-2006
[4640]
Sorry, I mean you eval-template function can create a context on 
the fly with the words in it.
Joe
22-May-2006
[4641]
ok Anton, I will try to implement this with your approach
Anton
22-May-2006
[4642]
It's not a terribly easy thing to do, but can be done.
Joe
22-May-2006
[4643]
Gregg, the GOAL is to be able to have a generic eval-template function 
that can evaluate multiple templates without having to include hundreds 
of locals in eval template. The values are generated dynamically 
with a code-block e.g. eval-template template code-block where code-block 
is [title: func-title "aha" tag1: emit-whatever ...