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
[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"]).