AltME groups: search
Help · search scripts · search articles · search mailing listresults summary
world | hits |
r4wp | 4382 |
r3wp | 44224 |
total: | 48606 |
results window for this page: [start: 17601 end: 17700]
world-name: r3wp
Group: I'm new ... Ask any question, and a helpful person will try to answer. [web-public] | ||
Pekr: 14-Apr-2009 | btw - do you use parse/all? I prefer to use parse with the refinement, because using plain 'parse ignores whitespaces, and I don't like when the engine messes with things instead of me :-) | |
sqlab: 14-Apr-2009 | I am not sure that I understand your intention. Do you want just interface ATM0.1, then you have to switch the order of your interface rule, as the condition to #"^/" (newline) is already true and done, and your cursor behind "point-to-point". As the first part is true, the second will never be done. | |
Pekr: 14-Apr-2009 | you can also use rebol and call php or perl for some stuff :-) However - you rules could be made - you just need to scatter it into sections and find some rules for the parsed file structure. | |
PeterWood: 15-Apr-2009 | In case this isn't clear. I'll try to explain the parse rule. First any effectively says to match any of the rules in the following block until the end of the string is reached. The first rule in the block is [interface copy int-text some name-char (print ["interface: " int-text)] says match with the word interface (newline + "interface ") then if there is a match, copy some name-char which says copy one or more characters which match the criteria of a name-char then if there are some name-char characters evaluate the rebol code in parentheses. If there wasn't a match with that first rule, then the second rule that follows the | will be applied. skip will pass over one character and always provides a match. | |
PeterWood: 16-Apr-2009 | Mike - The method that I showed you does not use up the "newline" at the end of the line. If you check again, the parse rule simply says copy in-text some name-char. This "stops" before the newline at the end of the line. In fact guessing at your requirements a little and assuming the name-char is available. Some thing along these lines should be close to what you want: keywords: ["^/interface " | "^/another keyword " | "^/yet another kerword"] parse/all lines [any [ copy int-keyword [keywords copy int-text some name-char ( print int-keyword ": " int-text] ) | skip ] ] {I obviously haven't tested this code.) | |
sqlab: 16-Apr-2009 | I see just two ways to get what you desire either you define different rules for interface at the beginning and interface after newline or you do it in a two pass way: first you separate the lines (either by parse or by read/lines) and then you process every line by itself. I would go the easy way with two passes. | |
Pekr: 16-Apr-2009 | uh, was on slow connection, so my reply got lost. Mhinson - there is no symbolic way to represent beginning of the line. I don't know any in any system. The only thing I know is end-of-line (newline). I know what you probably mean - you want to identify beginning of your lines, but even for first line (so not a rule, matching newline first, then next char = beginning of line). But - there is still various ways of how to do it. First - I think that your config files are chaos. Do they have any rules for some sections at all? :-) I also like what sqlab mentioned - sometimes it is easier to break stuff into 2 pass strategy. Read/lines is your friend here. You can try it on text files and you'll see, that the result is going to be a block of lines. I usually do: data: read/lines %my-data-file.txt ;--- remove empty lines from block of lines ... remove-each line data [empty? trim copy line] foreach line data [do something with data ....] Simply put - if rules for parser are out of my scope of capabilities (which happens easily with me :-), I try to find my other way around ... | |
Izkata: 16-Apr-2009 | Also, this is a bit slower, but avoids using complicated parse rules: >> lines: {junk Interface fa0 { ! { interface fa1} == "junk Interface fa0^/!^/interface fa1" >> SplitLines: parse/all lines {^/} ; {^/} is a string containing only the newline character, so this is a list of the separate lines == ["junk Interface fa0" "!" "interface fa1"] >> foreach line SplitLines [ [ if all [ [ not none? find line {interface} ;Find returns none! (equivalent of NULL or NIL) on "!" [ head? find line {interface} ;find goes to the first instance of what is being searched for, and head? checks if it's currently at the beginning of the line [ ][print line] [ ] interface fa1 ;The only match | |
Sunanda: 17-Apr-2009 | One huge parse may be technically neat. But it probably does not match the real world needs. Petr's (and other's advice) to break the problem down into managable (and separately debuggable chunks) is a good approach. And, remember, in the Real World, you may also need to track original line number (before removal of comments and blanks) to be able to give good error messages : "Bad data encountered near line 12,652" | |
Geomol: 17-Apr-2009 | You can parse strings and blocks. The /all refinement is used when parsing strings, not blocks. From your first comments, it seems, you're parsing blocks, so you don't need /all. What is lines? A string or a block? | |
Henrik: 17-Apr-2009 | the difference between using a set-word and SET word!: parse [a b c d] [ w1: word! (probe w1) w2: word! (probe w1 probe w2) set w3 word! (probe w1 probe w2 probe w3) w4: word! (probew1 probe w2 probe w3 probe w4/1) ] | |
Henrik: 17-Apr-2009 | A dialect is just a block of data that is processed in a certain way by REBOL. You can't evaluate it directly, but need some kind of parser to process it. You can create all sorts of crazy languages that way. Both the first and the second arguments to PARSE are dialects. The first one is the dialect block you provide to PARSE, the second one is the dialect used to process the first dialect. :-) | |
Henrik: 17-Apr-2009 | but unlike other languages that have to use regexp as a crutch for parsing, REBOL can use other methods than PARSE to process dialects. PARSE is useful in some cases and in other cases, there are better/simpler approaches for processing your dialect. | |
Henrik: 17-Apr-2009 | You are in dialect territory immediately when you are defining a block of data and wanting to do something other than evaluating it with DO. | |
Henrik: 17-Apr-2009 | But in another place, [1 2 3 4] might mean something entirely different. It also happens to evaluate as normal REBOL code: >> do [1 2 3 4] == 4 But of course it doesn't do much. :-) Code is data and data is code. | |
sqlab: 17-Apr-2009 | So parse has it's own language, that sometimes resembles to rebol, sometimes is different. And you can make your own languages or dialects too | |
Henrik: 17-Apr-2009 | I know the following sounds basic, but it's _crucial_ to understanding how REBOL works, otherwise you will not "get" REBOL: You must understand the concept that data is code and code is data. That means that anything you write, can be considered pure data. It's what you do with that data that becomes important. It's like speaking a sentence, but only paying attention to the placement of letters. That makes the sentence pure data. If you then pay attention to the words objectively, they can form a sentence, so you can validate its syntax. If you use the sentence in a context, you can apply meaning to it, subjectively. If you switch the context, the sentence can mean something entirely different. This is very important. Context and meaning. For REBOL: [I have a cat] This is a block with 4 words. It's pure data that can be stored in memory, but at that level it doesn't make any sense to REBOL. If you then apply a function to that data, you can process it. DO processes that data as REBOL code. It will be evaluated as REBOL code. Here it will produce an error, because it's not valid REBOL code. If you produce your own dialect, for example with PARSE, you can make that block make sense. When typing in the console, REBOL evaluates it as normal REBOL code by using DO internally. That means: >> now == 17-Apr-2009/18:13:14+2:00 is the same as: do [now] But this block: [now] is just pure innocent data with no meaning. | |
Brock: 17-Apr-2009 | 7.4 Marking Input: in the link provided by sqlab explains the use of set-words in the parse dialect. I needed to use this technique to strip out large comments from web logs that I was parsing and passing into a database. I was able to remove the large comment and replace it with a default string indicating "comments have been removed" | |
Brock: 17-Apr-2009 | This way you are only dealing with a small amount of data for each parse and might make it easier to visualize for you. | |
Pekr: 17-Apr-2009 | mhinson: now my explanations to some of your questions, as I think not everything was explained to you properly: 1) parse/all - /all refinement means, that string is parsed "as-is", because without the /all, white-space is skipped: >> parse "this white dog" ["this" "white" "dog"] == true >> parse/all "this white dog" ["this" "white" "dog"] == false >> parse/all "this white dog" ["this" " " "white" " " "dog"] == true I prefer to always use /all refinement for string parsing ... 2) i don't understand why there is | before "some", that code will not work imo ... 3) "ifa:" is a marker. Think about parse in following terms ... you have your data, here a string. Parse is the matching engine, which tries to match your input string according to given rules. In parse context (dialect) you have no means of how to manipulate the input string, except the copy. So markers are usually used, when you want to mark some position, then do something in parens, and then get back the position, or simply mark start: .... then somewhere later end: and in the paren (copy/part start end) to copy the text between the two marked positions ... 4) "skips till one of the OR conditions are met" - very well understood ... 5) Here's slight modification for append/only stuff. Type "help append" in the console. /only appends block value as a block. You will understand that, once you will need such behaviour, so far it can look kind of academic to you :-) I put parens there, to make more obvious, what parameters are consumed by what function .... >> wanted: copy [] == [] >> append (append wanted (copy/part "12345" 3)) interf: copy ["abc"] == ["123" "abc"] >> wanted: copy [] == [] >> append/only (append wanted (copy/part "12345" 3)) interf: copy ["abc"] == ["123" ["abc"]] | |
Henrik: 19-Apr-2009 | it would be interesting if the config file could be loaded, by making unloadable parts like $FW_OUTSIDE$ loadable using simple string replacable. Then you could just 'load the file into a block and it would be considerably easier to parse. | |
Steeve: 19-Apr-2009 | Pekr, I'm just disapointed by what mhinson produced after getting so many advices from Rebolers like you. The read/line trick is very useless, why doesn't he use the standard way of traversing newlines with parse ? And why using code (inside parents) to manage optional rules. Are commands like SOME, ANY, OPT not enough to manage simple rules like that ? | |
Henrik: 19-Apr-2009 | I don't yet understand why a block would be easier to parse than lines, by easier do you mean more efficient or easier to create the code? Yes, it's easier, because REBOL is based around this concept. Without this concept, dialects wouldn't make much sense. Your configuration file shown above is a good candidate for a dialect with some tweaks. I suggest, you read again what I wrote above about the basics of words, context and meaning. I can't emphasize enough how important this is to REBOL and especially for block parsing. It's important to understand this before moving on, or REBOL will remain difficult to use for you. Or drop your parse project for now and stick with the basics until you understand more of REBOL. is there a list of things I can't expect to load? The LOAD function will error out, if a string (such as a file you read) can't be loaded into a block of data. Try these in the console, and see which ones work: load "hello" load "hello," load "hello." load "%" load "1 2 3 4" load "hostname pig interface Null0 ! interface Loopback58 description SLA changed this" load %/c/temp/cisco.txt | |
sqlab: 19-Apr-2009 | I am against loading this configuation files. Why? -you can not control what is inside we know already, that there are elements unloadable by Rebol and the description almost always needs string parsing What would I change? I would either use only one temp variable in the parse rule and after just set to the new variable, as there is already a copy involved or I would use a meaningfull variable name in the first place | |
mhinson: 19-Apr-2009 | Good point about my temp1 temp2 etc. that was sloppy. It is true I cannot control what is inside the config files. They can contain any printable chars (eg in encrypted password fields or remarks/descriptions or embedded TCL code) and sometimes I am going to want to capture that text. I don't mind trying to do both methods as it will help me learn. Since I can't load the file directly I am thinking I will need to do a read %file.txt & replace the /\,[]%$()@:? with %xx etc. then load the result? I cant find a list of all the chars that I would need to treat like this yet. Henrik, I do continue to read what you have written, it is helpful & I think I am beginning to appreciate the concepts. I am probably not as clear as I should be about the specification of what I am trying to do so the code has tended towards listing the requirements rather than being elegant. Thanks /\/\ | |
mhinson: 19-Apr-2009 | Thanks. These files are getting better with more recent versions of Cisco IOS but sometimes trial and error is the only way to find the formats used. | |
mhinson: 19-Apr-2009 | I am still new and confused. where can I read about how to do this please? file: "%file.txt" host: "Router1" interface: "fa0" i: 25 description: [] ipaddr: "1.1.1.1 255.255.255.0" write/append/string %/c/temp/result.log [file tab i tab host tab interface tab description tab ipaddr newline] I want the output file to be a tab-seperated set of values but all I get is the text filetabitabhosttabinterfacetabdescriptiontabipaddrnewline | |
Graham: 19-Apr-2009 | should that be a function and not just a block? | |
Steeve: 19-Apr-2009 | What the need of flags and splitted lines, uh ? you can't write simple semantic ? Reading, your example file , you've got these simple rules. 1/ counting the lines line: [ thru newline (n: n + 1)] 2/ one interface mays contain several lines (infos) and is terminated by a line beginning by "!" interface: [ "interface" copy interface* line any [infos | #"!" line break] ] 3/ infos may be description, ip-adrr, ip-tables infos: [ " description " copy desc* line | " ip route " copy route* line | "ip address" copy ip-add* line ] That''s all folks, just parse the whole file with: parse/all [any [interface | line]] Please don't use read/lines or internal flags for such simple rules. | |
mhinson: 20-Apr-2009 | Thanks for pointing out the errors. The lines I want to group together are not all together in the file. But for the interface details they are. IP routes are grouped together under a vrf & the interfaces will relate to a particular vrf. The end of a section might be a "!" or might just be the beginning of the next section, or any non space or anything that does not match a pattern.. It depends on the particular section. I will try to reduce the number of rules I need and get a very clear view of what I am trying to achieve. I don't find the semantics of this very easy to grasp and I am still struggling to find any documentation that makes sense to me. Sorry to be asking so many questions but I not done any programming to speak of since Pascal the mid 1980s so I am sort of like a complete idiot as you see. Thanks for taking the time to suggest how much improvement is possible. | |
BrianH: 20-Apr-2009 | Try passing the string to TO-REBOL-FILE and then that will let you specify filenames with local file syntax. | |
Oldes: 20-Apr-2009 | Instead of: filename: none attempt [ filename: to-file system/options/args] if none? file-name [print "Bad command line" halt] I would use: if error? try [filename: to-file system/options/args][ print "Bad command line" halt ] I really don't like that people use the attemp in cases where they expect error. I use own attempt in cases where I don't expect error but still want to continue with execution (display and log the error). | |
mhinson: 21-Apr-2009 | That is very good and usefull thanks. Is there any way to get help on things like view layout [ slider ] please. I am paticularly keen to find how the data is returned from these controls. something like view layout [ h2 slider ] but that dosn't work.. there are hundreds of examples of how pretty the vid functions are, but I have failed to find much about using the results returned. | |
Geomol: 21-Apr-2009 | Now I both mention face and style. Styles are used to create faces. I guess, the GUI docs are not too clear in all of this. | |
Henrik: 21-Apr-2009 | LAYOUT is the VID dialect, which is REBOL's layout engine. When giving it a block of words, it produces a tree of objects, that each are a face. Each face contains sizes, offsets, colors, texts, event handlers and actions to perform when clicking on the face. | |
Henrik: 21-Apr-2009 | whoa, Anton is showing expert stuff there. it really should not be necessary to work with faces at that level. try settling for VIEW, LAYOUT, SET-FACE and GET-FACE for now. The next level would be events and the FEEL object. Then possibly STYLIZE. | |
Henrik: 21-Apr-2009 | but note that VID is lacking a lot in some areas, and that requires expert supervision (like Anton) to extend. it's excellent for smaller projects, though. | |
Sunanda: 21-Apr-2009 | This is a good tutorial, with examples of entering values, and the script responding to them: http://www.rebol.org/art-display-article.r?article=pfx654q | |
Sunanda: 21-Apr-2009 | and: http://www.rebol.org/ml-topic-index.r?i=vid | |
Henrik: 21-Apr-2009 | mhinson, have you tried running that line of code? Have you noticed that everytime you type something and press enter in the field, the contents is printed in the console? | |
mhinson: 21-Apr-2009 | I have just realised that in your line of code "field" is the name of one of the VID functions, so I understand that one now, thanks. If I use view layout [button "Ok" [name: get-face face print name]] it just returns "none", not down or up or true or false or clicked etc. I tried this view layout [button "Ok2" [name: value print name]] and it returns the text on the button does this mean get-face does not work on button? could I have predicted this? If I try to reference a different value like this view layout [button "Ok2" [name: value/text print name]] I just get an error & I have to restart the console to close the button. is this where I should be able to interpret print mold system/view/vid/vid-styles/button/feel to know how to ask for the parts of the value? Thanks very much for all the help. I am back at work now so can mostly only study this in the evenings. | |
Henrik: 22-Apr-2009 | mhinson, you've stumbled onto the first limitation. If we take the line of code apart, it does the following: view ; view the created layout layout ; create the layout (object tree of FACES) from the VID dialect block [ ; start of VID dialect block button ; the first element, a BUTTON "ok" ; the text for BUTTON [ ; start of the action block for the button. it's evaluated when the button is clicked. name: get-face face ; get the value of the button through the buttons GET-FACE accessor print name ; print the value (likely none) ] ; end of action block ] ; end of layout block Now when I say limitation, it's because you can't easily check for mouse button up, release, mouse movement, etc. The VID dialect directly uses a block right after the button description to describe what should happen after clicking the button. That's part of the syntax and above I wrote it as: <face style> <face text> [<action>] You can specify size, color, edge size, background image and a few grahpical effects. And with it being a dialect, you can leave things out or swap the ordering of some parameters. If you want more advanced control, you need to use the FEEL object, but you are definitely not ready for that. :-) Settle for working with VID and some layouts like above. VID was designed to be easy and very fast to use. If you go beyond VID, you will need a whole lot more knowledge on how to do things. | |
Henrik: 22-Apr-2009 | And if you type: ? b You get the entire content for that button face. | |
mhinson: 22-Apr-2009 | AH, this is a bit of a revelation.. Now I know where to find all those values. And I can use this sort of construct view layout [b: button "Hello!" [b/text: "goodbye"]] Thank you thank you thank you very much. | |
Henrik: 22-Apr-2009 | with that line, you need to know about SHOW and HIDE. If you set b/text like that, you need to do a: show b afterwards, or the face won't update. | |
Sunanda: 22-Apr-2009 | I think it's fair to say that VID and VIEW are built on top of the REBOL Core. They are not intimately part of REBOL itself, and may not always have had the same care lavished on them as the core of the language. So they tend to be a bit messier and fragmented. More of a work in progress than an attempt at the state of the art. | |
Anton: 22-Apr-2009 | To leave a trail, you could append to the draw block (without setting it to a new block each time, as you've done above), but that would mean your draw block would get very big over time. So a better thing to do is to draw onto an image!, which serves as a cache of your previous draw commands. For this, you can use an IMAGE instead of a BOX, and use the DRAW function to draw permanently onto the image. (The IMAGE style is very similar to BOX, but its 'image facet is set to an image! for us, ready to use.) | |
Anton: 23-Apr-2009 | The difference being we are using another word (IMG) to reference the image!, and the draw block (DRAW-BLK) is not created new each time, it is reused. Only the third value in the draw block is modified. That could become significant with large draw blocks. | |
Anton: 23-Apr-2009 | I advise you to review each facet in the face object: print mold first system/standard/face and compare with the slightly larger vid-face: print mold first system/view/vid/vid-face (Note, here FIRST is being used to return just the words of an object!, without their values. If you just probe a face it will fill up your console...) | |
Anton: 23-Apr-2009 | Once you find a specific facet you are interested in, you can then probe it to see its value: print mold get in face 'color ; == 200.200.200 and you can do this, of course, with any face you make, such as the BOX above. | |
mhinson: 28-Apr-2009 | Hi, I have continued to re-read the documentation for REBOL, and appreciating it more as I understand a bit more. Are there any puzzels I could try to write a solution to, in REBOL, that would be good for a beginner please? | |
Brock: 28-Apr-2009 | There is a puzzles group, and the corresponding puzzles answers group. However, I don't believe the puzzles are easy. | |
ChristianE: 28-Apr-2009 | Definitely these puzzles aren't for beginners. But have you already had a look at the cookbook at http://www.rebol.net/cookbook? That might be a good start trying to understand some of the examples there and go on from there ... | |
Sunanda: 29-Apr-2009 | And here's another one. In both cases, there were excellent procedural solutions and parse-based solutions. In both cases, the parse-based solutions were much faster: http://www.rebol.org/ml-display-thread.r?m=rmlPCJC | |
Maxim: 29-Apr-2009 | the get function evaluates a word and returns its value, the reduce function evaluates a block and leaves all the results within the block | |
Maxim: 29-Apr-2009 | in rebol, words are both litteral values and references to values. a word can also be unbound, in which case it essentially refers to no value. and dont kid yourself, this isn't as basic as you'd think :-) I still get bit, even fater years of rebol experience :-) | |
Sunanda: 29-Apr-2009 | It works, and it is more compact than my original -- so lots of bonus points there. It's worth reading on to look at some of the other procedural solutions, and Joel's analysis. That'll give you some good tips on how to solve a problem like this using REBOL's data manipulating tools. The parse solutions then take it to another level :-) | |
mhinson: 29-Apr-2009 | I still dont feel up to the parse version of the first puzzel, so I have had a go at the first part of the second puzzel. I think I am a bit confused about where to use var: 0 var: copy 0 I have also got a bit mixed up with the use of global variables which I know is bad. This is the code, which now dosnt seem to work since I put the variable initalisation inside the compress function, and tried to pass the variables to the function.. Dont laugh, but this is about 3 hours work. raw-data: [1 2 3 10 11 99 101 2000 2001 2002 2003 2004] sequence-break: func [count store result][ if/else (count > 1) [ append result to-pair rejoin [store "x" count] count: 1 ][ append result store ] ] compress: func [raw-data][count: 1 store: reduce raw-data/1 result: [] repeat i ((length? raw-data) - 1) [ if/else ((raw-data/(i) + 1) = (raw-data/(i + 1))) [ count: count + 1 ][ sequence-break count store result store: reduce raw-data/(i + 1) ] ] sequence-break count store result ] probe compress raw-data I am happy if my code is functional & easy to maintain at the moment. I will never be an application developer but using small bits of code to increase personal productivity is IMHO a very worthwhile thing to try and do. | |
Maxim: 29-Apr-2009 | I'll just note that you should use either instead of if/else ... the later is deprecated and slower | |
mhinson: 29-Apr-2009 | Thanks for the tips, so either exactly replaces if/else and I need to initalise series types with var: copy [] but not other types. These tips are great.. I just need to study it more & I shoud find my own bugs (and probably remember them too) Thanks very much | |
Sunanda: 30-Apr-2009 | We were all newbies once! And we all are again every time we start learning something new. I just remembered another puzzle/challenge I presented to the Mailing list, and got back a rich range of replies. This one is purely parse (including my first attempt), so trying it out, and then looking at others' code can help understand parse. As with the other two, it is based on a real-world need, rather than being a textboox exercise. (You experience the results of all three puzzles whenever you browse wwwREBOL.org). Good luck with this one too! http://www.rebol.org/ml-display-thread.r?m=rmlGPGQ | |
Sunanda: 30-Apr-2009 | And, just in case you had any more spare time in the next month, another one that really surprised me as being amenable to a parse solution: http://www.rebol.org/ml-display-thread.r?m=rmlJNFC | |
Maxim: 30-Apr-2009 | the ==3 printed is because >> probe funcA 2 3 doesn't grab any argument, so it evaluates funcA, evaluates 2, evaluates 3 and the console prints the last evaluation, so the would be 3. | |
Sunanda: 30-Apr-2009 | Regarding the many ways of creating a function. I always use 'func .... Life just seems too short to bother with the 'does and 'has shortcuts....The result of them is a standard function anyway. So, for me, the choice is between 'func and 'function. I've made the choice to use 'func, but I would have been just as happy to use 'function. It's a personal preference about how local variables are specified: f: func [a /local b][b: join a a return b] f: function [a][b][b: join a a return b] (though I may change my choice if I were dynamically creating functions rather than typing them :) | |
mhinson: 30-Apr-2009 | I was expecting funcA to be passed the values 2 & 3 funcA refer to them as argZ & argY FuncA to use local variables argA & argB & these variables to be given the content of argZ & argY funcA calls func1 and passes it values in argZ & argY func1 recieves values passed and refers to them as arg3 & arg4 func1 uses local vars arg1 & arg2 which are given the content of arg3 & arg4 func1 swaps position of values in arg1 & arg2 (so we know the function has worked) arg3 & arg4 are given the values of arg1 & arg2 func1 ends and passes the changed content of argZ & argY back to funcA that called it, but as argA & argB The end part of my code is wrong.. it should be argZ: argA argY: argB reduce [argZ argY] so expecting argZ & argY to takeon the content of argA & argB finaly passes the content of argZ & argY back to where it was called so the probe shows the swapped values. | |
Izkata: 30-Apr-2009 | Both functions use pass-by-value, so they can't affect the variables outside of themselves using internal references. And, nothing is being done with what func1 returns: >> func1 2 3 == [3 2] Try this: funcA: func [argZ argY /local argA argB][ argA: argZ argB: argY probe Retval: func1 argA argB argA: Retval/1 argB: Retval/2 reduce [argA argB] ] >> funcA 1 2 [2 1] ;printed by the "probe" == [2 1] ;returned from the function | |
Izkata: 30-Apr-2009 | In this case, the value passed into f2 is a string!, a subset of series! (block!, file!, and a couple others are also series!). Series! values are the equivalent of pass-by-reference, like how passing an array as an argument in C is pass-by-reference (or similar to it... I forget the exact terminology). Append works by modifying a series! without creating a new one. | |
Henrik: 30-Apr-2009 | It is very fundamental yes. You must see it as such: REBOL is very economical. It will aggresively reuse blocks and strings when it can. | |
Henrik: 30-Apr-2009 | And so if you specifically want to keep a series from being changed by some operation, you must copy it. | |
Henrik: 30-Apr-2009 | If you know when REBOL reuses series, you can make quite memory efficient and fast code. | |
mhinson: 30-Apr-2009 | ah.. this is good stuff.. And this (as expected) does NOT add 1 to dat5 each time it is called. dat5: 5 f5: func [dat5][ dat5: dat5 + 1 return dat5 ] print f5 dat5 print f5 dat5 I get it now, I just need to know how to recognise my types accurately. | |
Henrik: 30-Apr-2009 | Another important point: In the context of your function above, it doesn't actually matter whether the input is global. This is because REBOL works more on a basis of context rather than locals and globals. Locals and globals are probably what you are used to from other languages, but in REBOL that functionality is achieved through contexts. If the content of the context is allowed to survive, the content will survive. Try: boo: func [/local pond] [ pond: [] append pond 'fish ] >> boo boo == [fish fish] >> boo == [fish fish fish] No globals. :-) | |
Henrik: 30-Apr-2009 | Because the contents of a function is really a context, and once that function is created, it doesn't disappear, including the blocks and series that are existing in that function. (We have to be careful here about using the word "context" to describe what we say, and the concept of "contexts" in REBOL. Don't mix it up.) | |
Henrik: 30-Apr-2009 | The document you link to is exactly that phenomenon. It's both fundamental and very useful in REBOL for many things. | |
Gregg: 1-May-2009 | If you want to be non-greedy, you may need to use alternate rules and skip. e.g. s: {randomXXXrandom.log XXXrandom.txtrandom} parse/all s [ any [ "XXX" mark-1: | [mark-2: ".txt"] ( if all [mark-1 mark-2] [print copy/part mark-1 mark-2] ) | skip ] ] | |
Maxim: 1-May-2009 | I was used to regexp, when I used to program in python in particular, and that probably is one of the reasons I had soooo much of a hard time grasping parse (even after years of trying) | |
Gregg: 1-May-2009 | Yes, parse and regex are more different than alike. Parse is not designed to be concise. :-) | |
Maxim: 1-May-2009 | mike: the best tip I can give you is to picture a cursor in your head when you type your rules. parse really is about iterating over a series on byte at a time and matching the next expected characetr. | |
Maxim: 1-May-2009 | whenever it doesn't find what it expects, it "rolls back" to the last complete finished rule and tries the next one, if an alternative was given. this is hiercharchical. so if youre inside the 15th depth of parse ans suddenly an unexpected character is encountered, you might roll back up to the very first rule! | |
Maxim: 1-May-2009 | since it only moves forward, its very fast. in order to do look ahead assertion and things like that (which are slow in regexp anyways) you must learn a few tricks in order to manually set and retrieve the "current" character index. | |
Maxim: 1-May-2009 | also note that when there is a "roll back", the cursor and rules rolls back together. (unless you are doing manual cursor manipulation tricks) | |
Maxim: 1-May-2009 | so if your first rule only matched 2 characters, the second one fails, and other alternative is given... the alternative effectively starts checking at character 3 | |
Graham: 1-May-2009 | I presume that .txt is not going to appear in the 'random' text?? And XXX is really a fixed set of characters? | |
PeterWood: 2-May-2009 | I usually adopt a different approach which is to write a rule to match my target and use any and skip to apply that rule progressively through the input. It may not be the fastest way but it seems easier to grasp than backtracking. >> haystack: {randomXXXrandom.log XXXrandom.txtrandom} >> alpha: charset [#"a" - #"z" #"A" - #"Z"] == make bitset! #{ 0000000000000000FEFFFF07FEFFFF0700000000000000000000000000000000 } >> digit: charset [#"0" - #"9" ] == make bitset! #{ 000000000000FF03000000000000000000000000000000000000000000000000 } >> alphanumeric: union alpha digi t == make bitset! #{ 000000000000FF03FEFFFF07FEFFFF0700000000000000000000000000000000 } >> needle: ["XXX" some alphanumeric ".txt"] >> parse/all haystack [any [copy result needle (print skip result 3) | skip]] random.txt == true As you can see with this approach, you have to manually extract the "XXX" once you've grasped the needle. | |
Sunanda: 2-May-2009 | And this gives you easy access to many useful mailing list threads -- often containing "worked examples" in answer to specific problems: http://www.rebol.org/ml-topic-index.r?i=parse | |
Pekr: 2-May-2009 | to "b" | to "y" might not work as you would expect though. Better check what you are expecting, because you should really read it as - try to locate "b", and in the case you will not find it, try to locate "y". It simply does not mean find first occurance of "b" or "y", return the first match ... | |
Pekr: 2-May-2009 | Such functionality is long time request to parse enhancement, and is planned to be implemented ... | |
mhinson: 3-May-2009 | Hi, I have been studying the example from Pekr and developed the following addaptation. b: [to "bb" break] y: [to "yy" break] parse/all {zyybbc} [ some [b | y break | skip] copy result thru "c" (print result) ] however this seems to loop for ever, but I don't understand why. Any wise words would be appreciated. Sorry to be so needy, I am begining to wonder that as I am having so much trouble with this basic stuff, perhaps this is a programing language that I am just not suited to? Let me know if I am causing a problem by posting here so often & I will admit defeat with the parsing & go back to something more familiar.s | |
Maxim: 3-May-2009 | mhinson... for backtracking, at least in my experience, using to and thru are pretty dangerous... its pretty much the same as using a goto within structured programming. | |
Maxim: 3-May-2009 | I find that there several types of broad parse rule families. -some find and extract values OUT of some arbitrary string. -some are used as advanced controled structures, where you can pretty much simulate lisp functional programming, -some are used to convert data streams -others simply can match a whole data set to make sure it conforms. (+probably others) strangely each type of setup has sort of a different global approach, but its very case specific obviously. | |
Maxim: 3-May-2009 | where as in at what point in the string AND where in the sense of a what step are you now in the parsing. | |
Maxim: 3-May-2009 | lesson one, find text AFTER some identifiable (and unmistakable) token: | |
Maxim: 3-May-2009 | yes, and at least one rule must match or else it fails and rolls back to parent. rule | |
Maxim: 3-May-2009 | some will loop over and over until ALL rules fail. if that happens then IT fails too. | |
Maxim: 3-May-2009 | every other time (including after it matched the tag) the second, alternative, rule matched, and we where able to hit the end of the string. | |
[unknown: 5]: 3-May-2009 | the thing to know about parse mhinson is that you want to set forth the righ matching conditions to get to the end of the string that your parsing because if something doesn't match it will abort at that point and return false. | |
Maxim: 3-May-2009 | the "comprehension" of those simple things is essential, simply knowing about them is useless... cause in real life, you will have to "SEE" the whole recursive structure of the parse rules played in your head. if you don't fully grasp what is going on, you can't really create that essential mental map. that is what kept me from understanding parse for 6 yess... SIX years :-( and suddenly over the course of 2 days, I finally "GOT" it and a week later I was building a 700 line parse rule for a real-time server doing signal convertion from one data format to another through two network ports. | |
Maxim: 3-May-2009 | its funny cause once you "get" parse... just about every data manipulation is really easy using it. remark, used find and copy and shit like that before... it was a horrendous 100 lines of code. it was replaced by 10 lines of parse code and now runs 20-50 times faster and can do much more funky stuff on top of it. :-) | |
[unknown: 5]: 3-May-2009 | Yeah Maxim, my mind trys to believe something should be possible with parse and I always hit that roadblock when it isn't. | |
mhinson: 3-May-2009 | Ah, so Paul wants to create in effect a "regular expression" and use it in the parse. |
17601 / 48606 | 1 | 2 | 3 | 4 | 5 | ... | 175 | 176 | [177] | 178 | 179 | ... | 483 | 484 | 485 | 486 | 487 |