World: r3wp
[Core] Discuss core issues
older newer | first last |
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 ... |
older newer | first last |