r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[I'm new] Ask any question, and a helpful person will try to answer.

mhinson
8-Jun-2009
[2968]
I cant get the library to accept it :-(
make object! [
    code: 200
    type: 'syntax
    id: 'invalid
    arg1: "path"
    arg2: "intIpaddrS/"
    arg3: none

    near: {(line 68) write/append outFile reduce [either debug [currentFile 
    tab i tab] [""] hostname tab ipVrfForward tab interface tab vlan 
    tab mode tab trunkEncap tab nativeVlan tab allowedVlans tab upState 
    tab intDesc tab speed tab duplex tab intIpaddrS/(count1) tab QualifiedNetworkS/(count1) 
    tab tagMtu newline]}
    where: none
]
Graham
8-Jun-2009
[2969]
this is the error seen in the browser ??  ie. is the rebol org script 
that processes the uploads saying this?
Sunanda
9-Jun-2009
[2970]
The Library does sometimes have trouble with scripts.

It needs to load the script to get header information. But the Library 
is running on an older version of R2. Some newer scripts cannot be 
loaded as they contain syntax elements that crash the version the 
Library is running.
We have some creative work-arounds.

Mike can you email me your script (right click my name for email 
address). I'll see what the options are.
Thanks.....You are a natural at finding bugs!
mhinson
9-Jun-2009
[2971]
Hi, I have sent the whole thing to Sunanda as the script is ok in 
the browser, but has a few (other) problems being loaded into the 
Library. Probably down to me doing strange noobie things. In the 
case above the library prefers ... intIpaddrS/:count1 ...   Which 
seems better in any case so I have changed it.
Graham
9-Jun-2009
[2972]
yeah ..old rebol version
Sunanda
9-Jun-2009
[2973]
Thanks Mike.

It's [old REBOL version + REBOL not being backward compatible].


There is a theory that REBOL does not need to be backward compatible, 
as old applications can continue to run on older versions of the 
interpreter. That theory is fine in many cases.....


.....But it fails in the case of REBOL.org -- we're an old (verging 
on legacy) application that consumes REBOL code as data ..... We 
fail in some cases because the code we try to consume as data crashes 
the version of the interpreter we use.


I have an idea for (yet another) creative work around for the issue 
Mike has.....But I also have to spend a few days away from REBOL 
coding, so no immediate solution forthcoming. Sorry!
mhinson
10-Jun-2009
[2974x2]
Hi, is there any clever Rebol way to access the Tuples in this block 
by the associated numbers 80 & 4 please?
b: [80["8.8.8.8" "random"] 4["4.4.4.4"]]


if they were words it would be easy, but with numbers I am wondering 
if I just have to search for them & find the index & add one? Or 
perhaps convert the numbers into words by prepending them with a 
letter perhaps? Thanks.
This solution seems a bit messy, so I wondered if there was a neater 
way.
>> b: [_80["8.8.8.8" "random"] _4["4.4.4.4"]]
== [_80 ["8.8.8.8" "random"] _4 ["4.4.4.4"]]
>> b/_80
== ["8.8.8.8" "random"]
Sunanda
10-Jun-2009
[2976]
Select may help:
    first select b 80
    == "8.8.8.8"
mhinson
10-Jun-2009
[2977]
That is perfect....  Again I learn a new word for my Rebol conversations. 
 Thanks Sunanda
mhinson
13-Jun-2009
[2978]
Hi, I have written this function and would be glad of any comments 
please.  I know it is only simple stuff but I want to try any learn 
to write code well, not just hack stuff together that just about 
works.  Thanks. 
;; Generate all IPv4 dotted decimal masks
AllMasks: has [a b c d allMasks][
	allMasks: []
	if (allMasks = []) [
		for count 0 7 1 [ 
			i: to-integer power 2 (count)	
			a: 255.255.255.255 - to-tuple rejoin ["0.0.0." (i - 1) ""]
			b: 255.255.255.255 - to-tuple rejoin ["0.0." (i - 1) ".255"]
			c: 255.255.255.255 - to-tuple rejoin ["0." (i - 1) ".255.255"]

   d: 255.255.255.255 - to-tuple rejoin ["" (i - 1) ".255.255.255"]
			insert allMasks  reduce [a b c d]
		] 
		sort/all/reverse allMasks
		insert tail allMasks 0.0.0.0
		print "Created all IPv4 masks"  ;; debug
	] return allMasks
]
Sunanda
13-Jun-2009
[2979]
Any code that works is fine by me.....!

You could make your to-tuples a little tidier by utilising the fact 
the to-tuple will take a block of integers, eg:
    to-tuple [255 255 255 248]
    == 255.255.255.248
Paul
13-Jun-2009
[2980x2]
Hi mhinson, a couple things at first glance.  Beware setting a word 
to series data.  One of the big pitfalls newcomers have is that if 
they intend to reuse a function that contains a series being set 
that it can result in the series getting recursively populated.  
To avoid that we often use the 'copy word when setting series.  Although, 
by design sometimes we want the previous behavior.  The other thing 
is to get rid of the return at the end.  Just end your statement 
with allmasks.  You should really only need the 'return if you intend 
to pre-empt the full execution of the body block of the function.
Another tip while I'm here.  If you ever use the series pickers such 
as first, second etc.., then try to use them as the last item in 
logic functions.  For example:
series: [1 2 3]
if first series = 1 [true]
if 1 = first series [true]


The first logical expression will give you an error and the second 
will work correctly.
Sunanda
13-Jun-2009
[2982]
Use of 'return is partially a personal style issue. It is, literally, 
not needed if the last value your function handles is the one you 
want returned; in that case omiting the 'return can speed up a function 
considerably.


On the other hand, consider "literate programming" conventions: it 
can be polite to spell out the details so future code readers do 
not need to recapitulate your clevernesses just to work out what 
is returned......The code snippet below can return three separate 
things: spelling it out would help future generations!

    f: func [a b][
      either a > b [
          print a
         ][
         if a = b [b + 5]
        ]
     ]
mhinson
13-Jun-2009
[2983]
Hi guys, thanks for the tips, it is looking neater allready.

About setting the words to series data, is this us in my gode a bad 
example would you say?  I intended that the function would only ever 
need to calculate the values once, but perhaps my method is not secure?

Thanks for the tip about series pickers, that way looks a bit reversed 
so I would have probably got it wrong.
Sunanda
13-Jun-2009
[2984]
Another thought -- you may be able to avoid the block and to-tuple 
stuff by modifying a tuple:
    t: 255.255.255.255
    == 255.255.255.255
    t: poke t 4 t/4 - 1
    == 255.255.255.254
Izkata
13-Jun-2009
[2985]
I wouldn't call it a bad example of storing series data, exactly, 
just unusual.  Look at this:
>> foo: func [/local bar][
[    bar: []
[    if empty? bar [
[        print {Generating..}
[        insert bar 1
[        ]
[    return bar
[    ]
>> foo
Generating..
== [1]
>> foo
== [1]

If the function needs to be called multiple times, the data is stored 
and doesn't need to be re-created each call, getting a pretty good 
speedup.  This is what foo now looks like:
>> source foo
foo: func [/local bar][
    bar: [1] 
    if empty? bar [
        print "Generating.." 
        insert bar 1
    ] 
    return bar
]
mhinson
13-Jun-2009
[2986]
I didnt realise you could see the data stored by using SOURCE that 
is good.  I have pretty much changed it all together based on the 
extra information, so thanks.  Is this better or worse?  It is smaller, 
but it does more maths, but avoids the need to sort.
;; Generate all IPv4 dotted decimal masks
allMasks: has [t i allMasks][
	allMasks: [255.255.255.255] t: 255.255.255.255
	if allMasks = [255.255.255.255] [
		for count1 4 1 ( - 1) [ 
			for count 1 8 1 [
				i: to-integer power 2 count	
				t: poke t count1 (255 - (i - 1)) 
				insert tail allMasks t
			]
		]
	] allmasks
]
Gregg
13-Jun-2009
[2987x2]
AllMasks-2: has [mask t][
    mask: [255 254 252 248 240 224 192 128 0]
    allMasks-2: copy []
    repeat i 4 [
        t: 0.0.0.0
        repeat j i - 1 [t/:j: 255]
        foreach val mask [t/:i: val  append allMasks-2 t]
    ]
    allMasks-2: sort/reverse unique allMasks-2
]
I wouldn't worry at all about the amount of math being done, if you're 
planning to stick witht the memoizing approach.
mhinson
13-Jun-2009
[2989]
Thanks Greg.  Are there any disadvantages in using functions to memorize 
data?
Tomc
14-Jun-2009
[2990]
allMasks-3: has [t i][
 t: 255.255.255.255
 allMasks-3: [255.255.255.255]
 repeat here 4[
  i: 1
  loop 8[
   t/:here: 256 - i: i + i
   insert tail allMasks-3 t
  ]
 ]
 allMasks-3
]
mhinson
14-Jun-2009
[2991x2]
I like the simpler maths Tomc, I feel bad I din't spot that maths 
now :-) ... Have modified my version to use this & the simpler loop 
too, thanks.
I am wondering if there is a better or simpler way to get the index 
when using FIND? and the value is not found, my attempt seems more 
complex that I would have expected from Rebol, so I suspect there 
is a method or function I have not yet discovered.  :-)   Thanks.
a: find {abd} "e"
either none? a [i: 0][i: index? a]
Henrik
14-Jun-2009
[2993x2]
The second line can be:

any [all [a index? a] 0]
if you want to keep the 'either, it internally tests for none, so 
you could shorten it to:

i: either a [index? a][0]


You can see what kind of tests it makes by using TO-LOGIC on a value 
you want to test.
mhinson
14-Jun-2009
[2995]
Thanks for your help Henrik.  The ANY & ALL look like things I need 
to understand more.  I have seen & used them but not been able to 
appreciate what they are doing before. I think I may be ready to 
work that out now.  I am puzzled as to why index? is designed to 
produce an error on none, rather than return none perhaps.
Paul
14-Jun-2009
[2996]
Because the argument to index? is supposed to be a series and 'none 
is not a series.
mhinson
14-Jun-2009
[2997]
Then should FIND return an empty series if the target is not found? 
rather than none?  I thought none was a special case & might be handled 
differently by some functions that expect specific types.
Paul
14-Jun-2009
[2998x2]
yes find will return none if something isn't found.
But see Find returns none BASED on a series argument.  You were suppling 
'none as the argument.
Henrik
14-Jun-2009
[3000]
One can say that FIND limits its input to series! to eliminate errors 
as early as possible. Imagine if FIND accepted NONE and we had some 
intricate series of FINDs on a single block 'a:

find find find/reverse find a 'e string! 'f integer!
== none


If 'a is a dynamic block (not known when you write the code) where 
is the error?


It's not a great example, but it raises the question of how forgiving 
you want your functions to be, when you write them. I consider that 
you generally want to catch errors as early as possible, to avoid 
having to write "forgiving" code that can take up space and complicate 
things and worst of all, make the code much harder to debug. But 
it's only one school of thought.
mhinson
14-Jun-2009
[3001x2]
I see now HenriK, thanks for the explanation. So it encourages you 
to write code that is as deterministic as possiable and also make 
it more likely that you will need to understand your data fully too.
ANY & ALL are quite hard, but I think I am getting it..  This confused 
me for a while, but now I understand.
a: b: c: d: []

any [ do[a: 1 false] do[ all[ do[b: 2 false] do[c: 3 true]] true] 
do[ d: 4 true]]
print rejoin["a,b,c,d=" a "," b "," c "," d]
This is what I think is happening.  

a is set but as the block returns false the ANY block evaluation 
continues

b is set within the nested ALL block & as it returns false the ALL 
block evaluation stops

the do which contains the ALL block returns true so the ANY block 
evaluation stops
Izkata
14-Jun-2009
[3003]
Yes; ANY is a shortcut for OR'ing vaues together, and ALL is a shortcut 
for AND.
Henrik
14-Jun-2009
[3004]
I use ANY and ALL a lot because they can be handy in situations where 
an EITHER can be too cumbersome, such as inline result output for 
printing:

print any [select names name "No Name Found"]

In other cases they take up more space than an EITHER.
Tomc
14-Jun-2009
[3005x2]
unlike a series of and/or  any/all will stop evaulating conditions 
at the first condition that deternims the result
so the first true for any  and the first false for all
Gregg
14-Jun-2009
[3007x2]
Mike, memoizing has never caused me any technical problems. Just 
be sure to document it clearly.
I take that back, I've messed up a couple times and created uncontrolled 
growth in the memoized data. You do have to watch out for that. :-)
Oldes
15-Jun-2009
[3009]
instead of:
any [ do[a: 1 false] ]
why not to use just:
any [ (a: 1 false) ]
mhinson
15-Jun-2009
[3010]
That is interesting Oldes.  I thought I tried something like that, 
but now I see I must have been confused about what the () do.

so does the ANY cause the () to evaluate its contents?  If I just 
put [(true)] it is not evaluated, but all[(true)] is.   Then again 
to-logic [(false)] is not evaluated. There must be a trick I am missing 
here I think.  Thanks,
Gregg
15-Jun-2009
[3011x5]
Yes, ANY and ALL evaluate the block.
And parens are evaluated by default.
>> first [(true)]
== (true)
>> type? first [(true)]
== paren!
>> type? first reduce [(true)]
== logic!
One of my biggest AHA moments in REBOL was seeing that there is no 
code, only data that *may be* evaluated, and knowing when evaluation 
occurs is key (and easy to trip over :-).
Using blocks and *not* evaluating their contents--perhaps "deferring 
evalutation" is a better way to say it--is also a powerful aspect 
of REBOL. Being able to prevent parens from being evaluated is a 
good example.
mhinson
15-Jun-2009
[3016x2]
I think I would love to know when evaluation occurs.. So far I mostly 
just have to test every fragment of code I write & if I am lucky 
I guess right first time. I am slowly getting better at it, but I 
would say it is often a bit of a mystery.
I have submitted a script to the Library.  http://www.rebol.org/view-script.r?script=cisco-extract.r

Its purpose (apart from learning Rebol) is to read Cisco config files 
& present the interface information in a tab separated text file.