Is your goal to emulate find/any's behavior, or more to learn parse? I have a LIKE? func that does similar pattern matching, generating parse rules from a simple pattern grammar. Replace is a concise, if not the most efficient, way to break things up, and you handle compressed * runs as well, whcih is nice.
It doesn't work if * is the first or last thing in your pattern.
Gabriele
I think it will also fail if your pattern has colons in it.
Gregg
Good point Gab.
Marco
I found like.r and I will investigate it, thank you.
Marco
After investigatin like.r this is my second try:
find-any: func [ "Finds a value in a string using wildcards and returns the string at the start of it." series [series!] value [string!] /match /last /local str give_head emit pos pos2 non-wild-chars plain-chars tmp rule ][ last*: get 'last give_head: none str: copy to string! series value: copy value if empty? value [return none] ; normalize pattern while [find value "**"] [replace/all value "**" "*"] while [find value "*?"] [replace/all value "*?" "*"] if value = "*" [return series] if last [ value: reverse value str: reverse str ] if #"*" = first value [ remove value if not any [last match] [give_head: series] match: none ]
rule: copy [] parse/all value [ some [plain-chars | "*" (emit 'thru) | "?" (emit 'skip)] ] ; If the last thing in our pattern is thru, it won't work so we ; remove the trailing thru. if 'thru = last* rule [remove back tail rule] value: compose/deep [any [(all [none? match 'to]) (first rule) pos: (rule) pos2: to end | thru (first rule)] ] if none? parse/all str value [return none] if last [pos: skip series (length? series) - (index? pos2) + 1] any [give_head pos] ]
Perhaps still not perfect but should work in most cases.
Gregg
Sometimes I'll include a sampling of test cases, so people can see what's covered, and quickly try functions out.
Gabriele
I don't think that:
last*: get 'last
does what you expect it to do. You probably want:
last*: get in system/words 'last
Though, since I think you only use last* once, it may be easier to just replace last* with system/words/last, like:
if 'thru = system/words/last rule [...]
Steeve
Hi, it's been a while since I talked here (2 years ?)
Do you know if there is a better way to code this function ?
extend-mask: func[i][ ; set bits at the right of the MSB ; used to control if joining ADD operations together ; is allowed by their prefixed casting operation (and MASK). ; e.g. 00100100 => 00111111 ; Sorry if it's ugly since REBOL does not have a native for that. ; Well, the utility is rare, except when you write a code optimizer. int(2 ** (int (log-2 i) + 1) - 1) ]
(int) is a shortcut fot to-integer
Steeve
I don't want to use a precompiled array as a solution, the speed is not a problem... (currently)
Gregg
No quick suggestions here, but it's nice to see you again.
Geomol
Some ideas, but yours seem to be faster:
extend-mask: func [ i ][ i or either i > 0 [extend shift i 1] [0] ]
extend-mask: func [ i /local r ][ r: i while [0 < i: shift i 1] [r: r or i] r ]
hm, *extend* should be extend-mask in first one.
so a recursive
Gabriele
If speed is not a problem, then your version is probably the best choice.
If speed becomes a problem and you want to avoid floating point, there is a faster version of what Geomol proposed:
func [i] [ i: i or shift i 1 i: i or shift i 2 i: i or shift i 4 i: i or shift i 8 i or shift i 16 ]
You need an extra line if you are using R3 and 64 bits integers.
Geomol
That's neat, Gabriele!
It seems, Steeve only need the function to work on 8 bits at a time, so this is faster!
extend-mask: func [i] [i: i or shift i 1 i: i or shift i 2 i: i or shift i 4]
DideC
With Steeve func optimized, it's as fast as Gabriele's one on 8 bits :
In REBOL's case the interpretation overhead is probably much bigger than the floating point operations.
Steeve
Hi, playing with perf measures today. It comes that calling a function vs. inlining it gives a +20% speed overcost in my R3 version. And you people ?
>> f: does [1 + 1] >> comp 1000000 [1 + 1][f]
core 2.100.111.3.1 Windows win32-x86 20-Feb-2011/16:24:43 [1 + 1] 0:00:00.131209 [f] 0:00:00.15853 == 20% (on average)
I should add that I run REBOL with WINE on Ubuntu 32 bits.
Here the mezz I used for:
perf: func [n [integer!] b [block!] /local t] [ bind b 'n t: stats/timer repeat i n [n: i do b] stats/timer - t ] comp: func [n [integer!] a [block!] b [block!] /ref][ print reform bind [product version platform build] rebol ref: perf n [] ; time reference for empty code block a: to-decimal probe abs (perf n probe a) - ref b: to-decimal probe abs (perf n probe b) - ref to-percent (to-integer b - a / a * 100) / 100 ]