World: r3wp
[Core] Discuss core issues
older newer | first last |
Joe 22-May-2006 [4663x4] | a new attempt. The code that follows works except that I have to define the tags as locals, which is a pain when there are lots of them |
template: to block! "<html><head><title> title </title></head><body>tag1 tag2 tag3</body></html>" blk: remove-each val copy template [tag? val] ?? blk ; == [title tag1 tag2 tag3] eval-template: func [ /local res title tag1 tag2 tag3 ][ res: copy "" bind/copy blk 'res title: "hey" tag1: "this is tag1^/" tag2: "i am tag 2^/" ;tag3: "might not be set^/" repend res bind/copy template 'res res ] probe eval-template | |
so in this example tag3 is none because it was not set in the body but this is clearly an error. I am trying to solve 2 things: | |
1) Not having to declare the locals title tag1 tag2 tag3 in the function spec but have them as locals (might not be possible) | |
Ladislav 22-May-2006 [4667] | that *is* possible if needed |
Joe 22-May-2006 [4668x2] | 2) detect when one of the variables has not been set . In the above example with locals defined this can easily be fixed by checking for tags that are none |
Ladislav, then if there is an elegant way to define the locals inside the function body given blk: [title tag1 tag2 tag3] my problem is solved | |
Gregg 22-May-2006 [4670] | Why not just use FUNCTION with your existing code body and spec; make eval-template funcs on the fly? |
Anton 22-May-2006 [4671x2] | You would have to define a function every time, yes. |
(for the same reason - contexts can't be extended with new words). | |
Joe 22-May-2006 [4673] | Yes, but how costly is this ? ( I currently can generate 1000 pages/minute) |
Gregg 22-May-2006 [4674] | I would still lean towards a higher level solution at some point, but this makes more sense to me than messing with bindings. |
Ladislav 22-May-2006 [4675] | ;This is one way how to do it: eval-template: lfunc [template [string!]][] [ res: copy "" bind/copy blk 'res title: "hey" tag1: "this is tag1^/" tag2: "i am tag 2^/" ;tag3: "might not be set^/" repend res bind/copy to block! template 'res res ] see http://www.fm.tul.cz/~ladislav/rebol/lfunc.rThis would throw an error if the tag3: line is commented |
Gregg 22-May-2006 [4676] | Profile it. :-) How many do you *need* to generate, how much data, how many tags, etc. There are a lot of variables here (no pun intended). |
Joe 22-May-2006 [4677x2] | there are three approaches so far: 1) building function everytime with locals (anton/gregg) 2) template object (anton) and 3) lfunc |
I am going to code this using lfunc for the simplicity it brings and see what I learn Thanks all | |
Ladislav 22-May-2006 [4679] | the LFUNC approach would cause an error if the 'TAG3 variable were used in the template, otherwise it wouldn't cause an error. Is that what you wanted? |
Anton 22-May-2006 [4680] | (if your templates are not changing, the corresponding template objects can be made once and reused many times). |
Joe 22-May-2006 [4681x3] | Ladislav, yes |
Anton, can you code the above example using the template object you proposed | |
Maybe lfunc should be something part of Rebol3 . | |
Ladislav 22-May-2006 [4684] | :-) |
Anton 22-May-2006 [4685x3] | ok, hang five. |
Paste this into your console: | |
make-template-context: func [ template /local words spec ][ words: remove-each val to-block template [tag? val] spec: words forall spec [spec/1: to-set-word spec/1] append spec none context spec ] eval-template: func [ template-ctx code /local err ][ unset bind next first template-ctx template-ctx ; unset all words in the context do bind code template-ctx ; do the code ; Check if any tags were not set if find next second template-ctx unset! [ ; were any tags not set ? print "Some tags were not set!" foreach word next first template-ctx [ if not value? in template-ctx word [ print [word "is unset!"] ] ] ] ] ; now test template: "<html><head><title> title </title></head><body>tag1 tag2 tag3</body></html>" template-context: make-template-context template eval-tags: [ title: "web page" tag1: "tag1" tag2: "tag2" tag3: "tag3" ] eval-template template-context eval-tags ; <- this sets all expected tags and is ok eval-template template-context [] ; <- this doesn't set any tags so will complain and show all unset tags | |
Joe 22-May-2006 [4688] | I am using altme on linux. How do I get the clipboard to work ? |
Henrik 22-May-2006 [4689] | I think by using the middle mouse button |
Joe 22-May-2006 [4690x2] | nope, clipboard is broken in linux |
anton, thanks for your example, it's quite useful | |
Anton 22-May-2006 [4692] | You're welcome. |
Joe 22-May-2006 [4693x2] | ZZ |
didn't mean to type it | |
Frank 22-May-2006 [4695] | Clipboard on linux : ctrl-v in altme and middle mouse button in a text editor, it works for me |
Joe 22-May-2006 [4696] | Frank, yes thanks. For me is ctrl-C + middle mouse |
Henrik 22-May-2006 [4697] | Why can't I find paths in a loadable block? >> t: [x/y] == [x/y] >> type? first t == path! >> find t 'x/y == none >> find t to-path 'x/y == none |
Anton 23-May-2006 [4698] | I think the answer is: "because there is a bug." |
BrianH 23-May-2006 [4699x2] | Paths are structures like blocks. Find doesn't do structure analysis on block types like that - it just tries to determine if the exact same path is there, not another that resembles it. |
Use find/only and your path! will be found. | |
Henrik 23-May-2006 [4701x2] | >> t: [x/y] == [x/y] >> type? first t == path! >> type? 'x/y == path! >> equal? 'x/y first t == true One would think that find would be able to find it anyway |
ah! thanks | |
BrianH 23-May-2006 [4703x2] | >> find/only [x/y] 'x/y == [x/y] find [x y] 'x/y == [x y] |
Find can be unexpectedly fun at times. | |
Henrik 23-May-2006 [4705] | yes, it's very fun especially when you are on a time limit :-) |
Anton 23-May-2006 [4706] | Brian is right, the more complex "object" types are compared using same?: >> equal? 'x/y 'x/y == true >> same? 'x/y 'x/y == false |
BrianH 23-May-2006 [4707x3] | When searching in a string type for any string type, the type is converted. Same for block types. And path! is a block type. |
The only way to avoid the conversion is to use /only. | |
I was wrong earlier about the reason Henrik's find didn't work. | |
Anton 23-May-2006 [4710] | yes, my initial reply was a bit hasty too. |
Ashley 23-May-2006 [4711x2] | Don't know whether this has been discussed / RAMBOed yet, but I think a smarter reduce (either a refinement or another word) which could handle: reduce [now then] instead of requiring: reduce [now 'then] or compose [(now) then] would make writing dialects a lot easier as unset! is rarely a legitimate value within a dialect (i.e. I'd like to reduce blocks before parsing and words without a value should just be left as is). |
Something like: reduce2: make function! [ block [block!] "Block to reduce" /deep "Reduce nested blocks" /local blk "Evaluates a block of expressions, skipping words without a value, and returns a block." ] [ blk: copy [] foreach word block [ either block? word [ either deep [ insert/only tail blk reduce2/deep word ] [insert/only tail blk word] ] [insert tail blk either value? word [do word] [word]] ] blk ] >> reduce2 [red x now now/date (1 + 1) [red x now now/date (1 + 1)]] == [255.0.0 x 24-May-2006/13:12:14+10:00 24-May-2006 2 [red x now now/date (1 + 1)]] >> reduce2/deep [red x now now/date (1 + 1) [red x now now/date (1 + 1)]] == [255.0.0 x 24-May-2006/13:12:26+10:00 24-May-2006 2 [255.0.0 x 24-May-2006/13:12:26+10:00 24-May-2006 2]] but as a native! and able to handle funcs with args (e.g. reduce2 [print "hi"]). | |
older newer | first last |