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
29-Apr-2009
[1894]
I have a plan, but I am stuck before that as I can't work out how 
to reference the value of a variable in a block.
aa: 1  bb: 2  cc: [aa bb]  print first cc

I want it to print 1, but however I arange the brackets I can work 
out how to do it..  I know this is very basic, sorry.
Henrik
29-Apr-2009
[1895]
You can do one of two things:

aa: 1 bb: 2 cc: reduce [aa bb] print first cc

aa: 1 bb: 2 cc: [aa bb] print get first cc
Maxim
29-Apr-2009
[1896x4]
the get  function evaluates a word and returns its value, 

the reduce function evaluates a block and leaves all the results 
within the block
(to complement henrik's example)
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  :-)
oops  fater=after...  darn I'm really infected by the reichart keyboard 
syndrome  ;-)
mhinson
29-Apr-2009
[1900x2]
Thanks, that has bought me back to the position that there is an 
outside chance I can solve this. 

What was getting me was that sometimes print reduce cc/1 would return 
an interger & sometimes a word & I couldn't work out why.

storing the integers in the block  as suggested  cc: reduce [aa bb] 
makes it work right through my code. :-)  Thanks.
This is my first crack at it...  
blob: [1 23 25 26 27 26 24 2 13 56 57 58 59 34 23 7]
score: copy 0
top-score: copy [0 0]

repeat i (length? blob) [if/else ((blob/(i) + 1) = (blob/(i + 1))) 
[
	score: score + 1
	if (score > top-score/1) [
		top-score: reduce [score i]]
	][
	score: 0
	]
]
probe top-score

print rejoin [(blob/((top-score/2) + 1 ) - (top-score/1)) "--" blob/((top-score/2) 
+ 1 )]


Reading on I see it being solved with parse.. I will try to understand 
that now if I can...  I also realise my solution would be better 
if the repeat loop was 1 less than length. However running over the 
length seems to have no bad consequence in this case.  Thanks for 
the chalange & help.
Sunanda
29-Apr-2009
[1902]
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
[1903]
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
[1904x4]
I'll just note that you should use either instead of if/else  ... 
the later is deprecated and slower
so it would be:

either (count > 1) [
you'd use  var: 0  since 0 (an integer!)  is not a series type of 
data.
I don't have the time right now to debug the whole of it though... 
 ':-/
mhinson
29-Apr-2009
[1908]
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
BrianH
29-Apr-2009
[1909]
Object types are reference types too, but you usually need to do 
other tricks instead of COPY with them.
mhinson
29-Apr-2009
[1910]
Many thanks for taking an interest in my newbie fumblings.
Sunanda
30-Apr-2009
[1911x2]
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
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
mhinson
30-Apr-2009
[1913]
Hi, thanks for the extra puzzles.


I have managed to write a version that works now, but I am frustrated 
because I cant understand how to keep variables local & pass them 
to my function & return the changed values back...  In previous programming 
experience I seem to remeber that the function header listed the 
variable names & types used localy, then the function was called 
with the variables of the right type in the right order.. I cant 
remeber how results were returned in that context.


I have been reading here http://www.rebol.com/docs/core23/rebolcore-9.html#section-3.5
but every way I try seems to stop the code working as expected.

raw-data: [1 2 3 10 11 99 101 2000 2001 2002 2003 2004]

sequence-break: func [][
	either (count > 1) [
		append result to-pair rejoin [store "x" count]
		count: 1
		reduce [count result]
	][
		append result store
		reduce result
	]
]

compress: func [raw-data][
	count: 1
	store: reduce raw-data/1
	result: copy []

 repeat i ((length? raw-data) - 1) [either ((raw-data/(i) + 1) = (raw-data/(i 
 + 1))) [
			count: count + 1 
		][
			sequence-break count result store
			store: reduce raw-data/(i + 1)
		]
	]
	sequence-break count result store
	reduce result
]

print compress raw-data
Maxim
30-Apr-2009
[1914x4]
here is how to declare a local word using func

my-func: func [arg1 /local my-lcl][
	print arg1
	print my-lcl
]

my-lcl: "NOT"

my-func "YEP"

==
arg1
 
none
there are three other function! type building functions:
DOES
HAS
FUNCTION

look them up in the online rebol dictionary: 
http://www.rebol.com/docs/dictionary.html

you can also get help directly in the rebol console:

>> help does
USAGE:
    DOES body

DESCRIPTION:

     A shortcut to define a function that has no arguments or locals.
     DOES is a function value.

ARGUMENTS:
     body -- The body block of the function (Type: block)

(SPECIAL ATTRIBUTES)
     catch
you can also see its source, when its mezzanine code (standard rebol 
function written in rebol itself)

>> source does
does: func [

    {A shortcut to define a function that has no arguments or locals.}
    [catch]
    body [block!] "The body block of the function"
][
    throw-on-error [make function! [] body]
]
HTH !
mhinson
30-Apr-2009
[1918]
Great, this will help a lot, thanks.

I am beginning to realise that just because I have found a way to 
create a function (e.g. func) that dosn't mean I have found ALL the 
ways to make a function.  This seems to be a common theme in REBOL 
& has caught me out before.


This is my interpretation of what you have said & what I have read, 
however it does not work so I am obviously misunderstanding the method.

;; I am expecting this to reverse the arguements by passing them 
to a second function, while keeping all the function variables local 
& just passing back the result.

func1: func [/local arg1 arg2][
	temp: arg1
	arg1: arg2
	arg2: arg1
	reduce [arg1 arg2]
]

funcA: func [/local argA argB][
	func1 argA argB
	reduce [argA argB]
]

probe funcA 2 3

>> probe funcA 2 3
[none none]
== 3
>>
Izkata
30-Apr-2009
[1919]
As written, neither funcA nor func1 take any arguments - the variables 
listed are after the "/local" key that turns them into local variables 
initialized to none
Maxim
30-Apr-2009
[1920]
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.
mhinson
30-Apr-2009
[1921]
wow!  so do I need to pass them my globals & copy them in the function?

I expected that copy to be implicit....  I better look at DOES HAS 
& FUNCTION before I waste anymore of everyones time. sorry.
Izkata
30-Apr-2009
[1922x2]
So,

func1: func [arg1 arg2 /local temp][
	temp: arg1
	arg1: arg2

 arg2: temp  ;I think this was a mis-type in you original, if you 
 wanted to swap
	reduce [arg1 arg2]
]
an easier way would be:

func1: func [arg1 arg2][
	reduce [arg2 arg1]
]
mhinson
30-Apr-2009
[1924]
I am not after efficency, just trying to understand local & global 
vairable passing.

so reading the above I would expect this clumsy thing to work .. 
but it dosn't


func1: func [arg3 arg4 /local arg1 arg2 temp][
	arg1: arg3
	arg2: arg4
	temp: arg1
	arg1: arg2
	arg2: temp
	arg3: arg1
	arg4: arg2
	reduce [arg3 arg4]
]

funcA: func [argZ argY /local argA argB][
    argA: argZ
	argB: argY
	func1 argA argB
	argA: argZ
	argB: argY
	reduce [argA argB]
]

probe funcA 2 3
Henrik
30-Apr-2009
[1925x2]
What outcome are you expecting?
Also note that in funcA in your last bit pasted, func1 has no effect.
Sunanda
30-Apr-2009
[1927]
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
[1928]
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
[1929x2]
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
(Also, I just copy/pasted without adding Retval to the local variable 
list)
mhinson
30-Apr-2009
[1931x2]
Thanks, the key to my understanding this time was that

Both functions use pass-by-value, so they can't affect the variables 
outside of themselves using internal references

I was under the mistaken impression that all the variables unless 
explicitly made local, would be global.   Thanks for putting me on 
the right path again.
ah, I can see why I was confused.. this function
dat2: "-"
f2: func [dat2] ["operating on the global"
	append dat2 "+"
	return "added"
]
print f2 dat2
print dat2
print f2 dat2
print dat2


keeps adding a "+" to dat2, but if only the value of dat2 is passed 
to the function I cant see why is is not just doing 
append "-" "+"

which would not seem to have any effect on dat2..  so in this case 
dat2 seems to be global.   ~~confused~~
Izkata
30-Apr-2009
[1933]
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
[1934]
the value is not copied, which is why it keeps appending.
mhinson
30-Apr-2009
[1935]
Now I have seen references to this behaviour & the need to use "copy" 
in some contexts, but I have not managed to understand it yet.
I suspect it is a very fundemental thing to grasp.
Henrik
30-Apr-2009
[1936x2]
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.
And so if you specifically want to keep a series from being changed 
by some operation, you must copy it.
mhinson
30-Apr-2009
[1938]
ah. so this is for variables containing series types only? numbers 
get passed as values (which is in effect a copy?)
Henrik
30-Apr-2009
[1939x4]
If you type:

>> ""


in the console. A string is allocated. You can't reuse it here, because 
you haven't referenced it to get back to it. But it would stay in 
memory until it's garbage collected.

But in this code:

>> loop 10 [append "" 1]
== "1111111111"


The string can be obtained again by the code itself. REBOL reuses 
the string.
Series, yes. You can also reference objects this way.


Another trap is that series within series are also reused. This is 
why COPY/DEEP exists.
If you know when REBOL reuses series, you can make quite memory efficient 
and fast code.
If you don't know, then you can get some strange bugs. If a series 
changes without an apparent reason, then it's likely due to whether 
it's copied or not.
mhinson
30-Apr-2009
[1943]
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.