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
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.
mhinson
17-Jun-2009
[3018]
Hi, I have done a bit with fairly basic parse expressions, but I 
am now trying to understand more.

Am I right to think that ALL SOME & ANY are the only controls of 
this type?  Or am I missing another in the set?

Do ALL & ANY work in the parse dialect the same way that they do 
described above?  Thanks.
BrianH
17-Jun-2009
[3019]
ALL is not an operation in the parse dialect. ANY and SOME are looping 
operations in parse.
mhinson
17-Jun-2009
[3020x2]
Ah. that is why I am getting erros with it.  I thought I was just 
using it wrongly. Thanks.
The errors are rather cryptic
BrianH
17-Jun-2009
[3022]
ANY is like regex *, SOME is like regex +, OPT is like regex ?.
mhinson
17-Jun-2009
[3023]
is there any way to get rebol help on the parse dialect?   like ? 
PRINT etc please?
BrianH
17-Jun-2009
[3024]
You have to look online, sorry.
mhinson
17-Jun-2009
[3025]
ok.  I really like the ? help functions. While learning they help 
a great deal.  Thanks.
BrianH
17-Jun-2009
[3026]
Unfortunately, parsing is considered a hard subject. Learning PARSE 
might take some time if you haven't had experience or taken a class 
in parsing before, even when you read the online docs.
Pekr
17-Jun-2009
[3027]
Do you think proposed parse enhancement will slow parse performance?