Printf
[1/7] from: tim::johnsons-web::com at: 20-Dec-2003 12:19
Hello Rebols:
I'm a parse-a-phobic, and use it infrequently.
The following function uses 'parse dialect, and appears
to work, but I'd appreciate a critique from anyone on
it. Given my unfamiliarity with parse, you just might
be preventing me from chasing a bug sometime:
Thanks!
Code follows:
; Replace "%s" with members of a block. In the spirit
; of C, LISP, python format strings
printf: function[str[string!] subs[block!]]
[delims non-delims blk ndx ][
delims: charset "%s"
non-delims: complement delims
blk: copy []
ndx: 1
parse/all str[
some [
copy txt some non-delims (
append blk txt
if ndx <= (length? subs)[
append blk subs/:ndx
]
ndx: ndx + 1
) |
delims
] ; end some
]
rejoin blk
];end func
;I appreciate the input, also, there used to be a function
;posted at rebol.org that might have done something similar.
;Couldn't find it last I looked.
Regards
--
Tim Johnson <[tim--johnsons-web--com]>
http://www.alaska-internet-solutions.com
[2/7] from: stasil213:ya:hoo at: 23-Dec-2003 1:32
Tim,
I'm relatively new to dialects, too, but I gave it a try.
Though the gurus can probably do it better, I have discovered that the rule
copy x skip (append block x)
works like an "else do nothing" at the end of a string substituion parse.
I did get it to keep the s's, but my code can probably be made much more
effiecient, and tested a lot better.
Merry Christmas to all,
Stan Silver
REBOL [
Title: "printf"
Author: "Tim Johnson"
ModifiedBy: "Stan Silver"
]
printf: function[str[string!] subs[block!]]
[delims non-delims blk ndx ][
delims: charset "%s"
non-delims: complement delims
blk: copy []
ndx: 1
parse/all str[
some [
copy txt some non-delims (
append blk txt
if ndx <= (length? subs)[
append blk subs/:ndx
]
ndx: ndx + 1
) |
delims
] ; end some
]
rejoin blk
];end func
printf2: function[str [string!] subs [block!]]
[delim blk ndx x][
delim: "%s"
blk: copy []
ndx: 1
parse/all str [
some [
delim
( if ndx <= (length? subs)[
append blk subs/:ndx
]
ndx: ndx + 1
)
|
copy x skip (append blk x)
] ; end some
]; end parse
rejoin blk
];end func
; ======;
; TESTS ;
; ======;
???: func [result 'ignore desired] [
if not (result = desired) [
print ["TEST FAILED" mold result ignore mold desired]
]
]
??? printf "doesn't%skeep%sthe_s's" [1 2] >> "doe1n't2keepthe_'"
??? printf2 "does%skeep%sthe_s's" [1 2] >> "does1keep2the_s's"
??? 'should >> 'fail
[3/7] from: SunandaDH:aol at: 22-Dec-2003 19:50
Hi Tim,
> I'm a parse-a-phobic, and use it infrequently.
> The following function uses 'parse dialect, and appears
> to work, but I'd appreciate a critique from anyone on
> it. Given my unfamiliarity with parse, you just might
> be preventing me from chasing a bug sometime:
I'm completely hopeless at Parse too.
And this isn't exactly the same as you are looking for. But have you looked
at build-markup and build-tag ?
http://www.rebol.com/docs/changes.html#section-3.11
Sunanda.
[4/7] from: tim:johnsons-web at: 22-Dec-2003 17:14
* [SunandaDH--aol--com] <[SunandaDH--aol--com]> [031222 16:12]:
> Hi Tim,
> > I'm a parse-a-phobic, and use it infrequently.
<<quoted lines omitted: 3>>
> > be preventing me from chasing a bug sometime:
> I'm completely hopeless at Parse too.
Hiya Sunanda:
:-) I just have to get into it. I've got a couple of functions
doing this, using basic rebol list traversing, and
I believe the 'parse is going to give me a higher performance...
tj
> And this isn't exactly the same as you are looking for. But have you looked
> at build-markup and build-tag ?
<<quoted lines omitted: 3>>
> To unsubscribe from this list, just send an email to
> [rebol-request--rebol--com] with unsubscribe as the subject.
--
Tim Johnson <[tim--johnsons-web--com]>
http://www.alaska-internet-solutions.com
[5/7] from: tim:johnsons-web at: 22-Dec-2003 17:23
* Stan Silver <[stasil213--yahoo--com]> [031222 15:59]:
> Tim,
>
> I'm relatively new to dialects, too, but I gave it a try.
Hi Stan:
Ahah! I think you nailed it by adding the 'skip in printf2
- that is one thing I was missing
I made one more change, so that 'subs is wrapped backed
to the begining if there are more delims than subs.
Thanks! My addition is below:
Happy Holidays
tim (still trolling for gurus :-))
;; *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
printf2: function[str [string!] subs [block!]]
[delim blk ndx x][
delim: "%s"
blk: copy []
ndx: 1
parse/all str [
some [
delim
(
append blk subs/:ndx
either ndx < (length? subs)[
ndx: ndx + 1
][ ; more delims that subs
ndx: 1 ; 'wrap' subs
]
)
|
copy x skip (append blk x)
] ; end some
]; end parse
rejoin blk
];end func
> Though the gurus can probably do it better, I have discovered that the rule
> copy x skip (append block x)
<<quoted lines omitted: 61>>
> To unsubscribe from this list, just send an email to
> [rebol-request--rebol--com] with unsubscribe as the subject.
--
Tim Johnson <[tim--johnsons-web--com]>
http://www.alaska-internet-solutions.com
[6/7] from: tim:johnsons-web at: 23-Dec-2003 8:13
Hello List:
This was sent back to me OTL. Since I think it is a valuable
contribution on the subject of 'parse and advises regarding
some pitfalls, I'm posting this back to the list for archival
purposes and adding some comments.
Really good contribution.
Thanks Tom
tj
* Tom Conlin <[tomc--darkwing--uoregon--edu]> [031222 20:38]:
> Hi Tim
> I just looked at your parses
<<quoted lines omitted: 11>>
> delims: charset "%s" ;;; DANGER sets do not respect ordering
> non-delims: complement delims
Not pre-allocating introduces the possibility of high overhead
in interative blocks..... Very good point. In my non-parse function,
I wrap the function in an anonymous object, intiallize an 'alloc
word to a value of 128, and make algorithmic adjustments to that
size based on the length of the return value. (which is a string)
> ;;;it starts a string and ends a string why a block in the middle?
> ;;; pre-allocating the correct length is golden
> ;;; and this result can't get any longer
> blk: make string! add length? str length? to string! subs
Also, it is arguably not good programming practice to use the 'circular
approach to the 'subs. After all, I've been programming with fixed
replacement lists in C and python for years and even GCC gets grumpy
about tokens and replacement lists being of a different length.
And since rebol will cheerfully insert a
none as a string subset, then I might end up
error trapping any overruns and dumping the 'circular approach.
That would eliminate the 'guessing'....
> parse/all str[
> some [
<<quoted lines omitted: 46>>
> ;;; an improved vesion,
> ;;; keeps the flavor you had going but should be free of structural errors
Tom's revisions below:
> printf22: func[str [string!] subs [block!] /local delim blk x][
> delim: "%s"
<<quoted lines omitted: 18>>
> blk
> ];end func
Different approach here: :-) Since I started programming on a
7.5 mhz 8086 with 640k of RAM, I'd be one to keep this out
of big loops....
> if I were writing it to begin with I would probable try to go
> more in the direction of replace in place ...
<<quoted lines omitted: 23>>
> str
> ]
--
Tim Johnson <[tim--johnsons-web--com]>
http://www.alaska-internet-solutions.com
[7/7] from: stasil213:ya:hoo at: 23-Dec-2003 21:48
Tim,
These suggestions are very helpful. Thanks for posting them. And thanks to
Tom!!
Stan
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted