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

World: r3wp

[!REBOL3-OLD1]

Maxim
2-Apr-2009
[12485x3]
contextualise module methods based on state  :-)
btw, I'm really sorry if I'm not participating in the R3 GUI effort... 
I'm just elsewhere in the GUI world... what you guys are doing, I've 
done so many times, on too many platforms, for it to be still *fun*.


a lot of people don't get that I use (and occasionally abuse) rebol 
for my own long-term goals.  its just the fastest prototyper out 
there.  Now that GLASS has officially started, the (eventual) end 
goals for it are sort of beyond current desktop/window/button/menu 
 concepts of GUI, even if that is what I am starting with, cause 
I need the bricks before building the wall.
but when R3 gets a bit more stable, most of the work done in R2 will 
go over R3.  I'll only have to recode one or two core libs for all 
the rest to function.
BrianH
2-Apr-2009
[12488]
Keep in mind that I am not really participating in the R3 GUI effort 
right now either - I've been working at a lower level. I write LOAD 
:)
Pekr
2-Apr-2009
[12489]
Maxim - you have strange aproach. On one hand, you claim you did 
GUI and object stuff so many times it is no more fun for you, but 
on the other hand you complain, that R3 does not allow OOP functionality 
x or y?
BrianH
2-Apr-2009
[12490]
And other mezzanine and intrinsic functions too, but I'm the author 
and designer of LOAD right now, and it doesn't get much lower :)
Maxim
2-Apr-2009
[12491x2]
pekr:  I rely on objects for much of my work.   I hate the profound 
OOP theory (polymorphism and some of the dark OOP concepts), but 
like carl and most rebolers, agree that the primitive object is a 
very worthwile concept.  As is the case for many paradigm, they sometimes 
evolve themselves into such a complex form, that they lose sight 
of their original DNA.  


have you ever tried to support traditional OOP applications with 
multi-level inheritance and accross the board polymorphism, double 
inheritance and some other things like templates and more... it all 
starts out nice, then it locks you in.  you eventually get stuck 
by the framework being so much work to evolve, that you just keep 
adding new things instead of fixing the old.
I didn't say I did object stuff many times, only the gui part of 
things.  I've been implementing gui apis for like 15 years, at various 
levels... all with the end goal of getting to GLASS.
Pekr
2-Apr-2009
[12493]
I worked with CA Visual Objects, which is trongly typed OOP. Most 
of the time you are trying to find out your way of how to obey system 
limitations. I hate that stuff. But - my question is different - 
with your  strong experience - why don't you just help with R3 GUI? 
;-)
Maxim
2-Apr-2009
[12494]
AND for the record... I didnt complain  ;-) just said that having 
accessors would allow us to make R3-based apis much more fun and 
easy to use  :-)
Pekr
2-Apr-2009
[12495]
... there is very few ppl contributing. Most of guys from here being 
invited to R3-gui showed no real input to Carl.
Maxim
2-Apr-2009
[12496x6]
hum,  tough answer... it would be a mix of time, desire, and past 
history.
my vision of computing has always been deeply rooted in dataflow. 
 I have talked to Carl about it, even shown him some of it at devcon, 
but it was decided at some point in the R3 circle that dataflow was 
an overkill for R3.
I do agree, in fact.
that is, until I get a solution that works end to end.  Ubiquitous 
application of dataflow at this point, is still an experiment.
my prototypes encourage me to continue, since, I am always amazed 
at how it behaves in the end, but I have still to merge all of the 
solution into one bundle.  and no, its not simple, and yes it takes 
more code than what Carl will build in R3.  but in the end, I'll 
be able to interconnect a field directly to a web-servers' cgi-like 
page online, without actually needing to code anything.   one litlte 
line of code will allow both to interact with each other.


once all is done it will be easy to grasp, but currently, even I 
have some "challenges".  good thing is that in keeping with dataflow's 
programmatic simplicity, porting GLASS to R3 will be dead easy.  

so long as liquid works on R3. the most work will be adapting liquid 
globs to R3's gob! type, and even there, it could be pretty simple, 
if R3 has draw and its similar...
There is no reason, GLASS and R3 VID can't co-exist, in any case. 
 Choice is always good.
ICarii
2-Apr-2009
[12502]
re contributing to 3.4 GUI - in the beginning I did testing and some 
creating but it became frustrating creating controls/widgets by always 
working around the various gotchya's that I decided to test only 
and wait for beta until trying to create complex widgets.  In the 
meantime i'm toying with my old onyx system and converting it to 
use geomal's GLServer.  I program for fun these days and if im not 
having 'fun' i move on to something that interests me more.
GiuseppeC
2-Apr-2009
[12503x2]
Maxim: please explain what you mean for accessors and why rebol has 
no accessors
For the others: if I have the following piece of code

Rebol []
o: make object! [
	a: 1
	b: 2
	]
x: make o [
	C: does [print [a + b]]
	]
o/a: 2
x/c


I expect that changing o/a also its value is inherithed in the object 
X and X/C should give 4 as results.
[unknown: 5]
2-Apr-2009
[12505]
Isn't that a bug?
Maxim
2-Apr-2009
[12506x7]
giuseppe no, it will give you 3.

o and x are unrelated after the make o.
it would work if you change o/a before you create the x object.
Accessors allow you to provide your own functions to how the code 
interacts with (accesses) the object internals.  typically you have 
get/set/print/convertion accessors.

the range and flexibility of accessors is largely dependent on the 
language and the speed considerations of implementing "public" accessors. 
 


most modern oop languages  implement accessors.  some languages, 
like python, let you change all the accessors which the language 
itself has access to.

one of the things accessors allows is to create or simulate custom 
datatypes (depending on how complete the accessor interface is).

so as an example, we could do this:

float-pair: object [
	x: 0.0
	y: 0.0
	set: func [value [string! pair! decimal!][
		switch 
	]
]
damn... the send got changed to Enter...  :-(
float-pair: context [
	x: 0.0
	y: 0.0
	set: func [value [pair! decimal!][
		switch type? [
			pair! [ x: to-decimal value/x y: to-decimal value/y]
			decimal! [x: value y: value]
		]
	]
]

then you would be allowed to do:
float-pair: 3.4
float-pair: 5x7


obviously, this is just a very simple and incomplete example but 
it should give you an idea of the concept.
the fun things with rebol is that we could potentially have series 
type accessors (insert, copy, pick, etc.)
btw, R2 we can create pseudo classes by implementing custom port 
schemes which include a concept of accessors.
Anton
3-Apr-2009
[12513]
[ This whole post is mainly in the R2 mindset, but is somewhat relevant 
also to R3. ]


The technique of setting words directly into the global context like 
this:

	context [
		set 'o ...
	]


I do not like, because this code is modifying its environment - it 
has side-effects - thus, it is non-modular, and does not scale.

Being non-modular means large software systems can't be built up 
reliably, because the cumulative effect of all those side-effects 
will eventually cause name-clashes in the global context, so that 
some word exported from one context will be overwritten by the same 
word exported from another context.

For example, suppose I've seen two graphics demos by two different 
authors. They each have an awesome graphics processing routine and 
I decide that I would like to combine both routines into a single 
program. They each wrapped their code up in a context and exported 
a word 'process-image, like so:

	; From author #1
	context [
		set 'process-image does ...
	]

	; From author #2
	context [
		set 'process-image func ...
	]


You can imagine that each of these "modules" also has a large amount 
of supporting code, local variables and functions, and each is in 
a large file on the respective author's website. Somewhere in the 
middle of each of these files, in the CONTEXT body code, are the 
SET lines which export the words into the global context.

When I write my program to combine both of these "modules", I will 
probably write code like:

	; Acquire all dependencies
	do %image-processor.r  ; By author #1
	do %super-gfx.r  ; By author #2

	; Create an image and manipulate it.
	my-image: make image! 400x400
	process-image my-image ...


and here I realise that there is a name-clash with the 'process-image 
word, which is set only to the value exported by the second author.
So what do I do?

Here are some theoretical approaches, which have their own problems.

1) I could reload each file just before use:

	do %image-processor.r  ; By author #1
	process-image my-image ...
	do %super-gfx.r
	process-image my-image ...


  Each "module" is not expecting to be used this way, so this has problems 
  like:

  - "Static" locals which are intended to remain in memory will be 
  lost each time the file is reloaded.

  - Performance could suffer; each file could be large, and many calls 
  to 'process-image might be done.


2) I could set the first imported word to my own chosen word before 
importing the second "module". eg

	do %image-processor.r  ; By author #1

 process-image2: :process-image  ; Create an alias, as 'process-image 
 will be overwritten next line.
	do %super-gfx.r  ; By author #2

	; Now use
	process-image2 my-image ...
	process-image my-image ...


  But this means that a line of code has been created in the dependency 
  acquisition stage which has a complex interdependence between the 
  two "modules". They are not independent, and so individual dependency 
  acquisition lines can't be easily copied from this code and pasted 
  into a new script and expected to work right away. If copy/pasted, 
  the code will have to be examined, probably in great detail, to discover 
  what's going on and how to make it work. This will lead right back 
  into each source file, where the SET lines which export words to 
  the global context must be found. What great fun that will be in 
  a large software system built using many modules.


Another approach could be to try to bind each module code to a new 
context which contains the exported words, so they are isolated from 
each other... but this is complex.


All the above approaches are attempting to work around a single problem: 
that each "module" is exporting words where and when it likes, without 
consideration for the environment (other "modules", other global 
words etc.) This is "global namespace pollution" and the approaches 
above just introduce more problems in trying to work around it.


The solution to all this, is, in my view, for modules to declare, 
in the script header, the words that are intended to be exported, 
but for the module code not to actually perform the exports. This 
should be done by the user code, at its option. If a large module 
provides an API of 10 functions, then those function words should 
not be forced into the global context. The user script should be 
able to choose which, if any, of those words to import, and into 
which context it would like to import them. Additionally, the exported 
word value should be importable to a differently-named word, which 
can solve the name-clash problem we have above.

If modules do not use SET, but instead declare their "export" words 
in the script header, then digging through code to find side-effects 
should no longer be necessary. In R2, this requires that all module 
authors adhere to this type of module system, and declare their "export" 
words in a standard fashion.


In R3, I'm hoping the module system will develop into one which can 
enforce the modularity of modules, so that a user script can be sure 
that there were no side-effects introduced by loading any module.
BrianH
3-Apr-2009
[12514]
Some comments about R3:
- R3 modules have the explicit Exports header in the spec

- IMPORT/only doesn't export the words into your current context, 
it just returns a module! reference.

- LOAD module! doesn't DO any of the code in a module, so you can 
examine the spec with SPEC-OF module!.

- If you import a module the first time with IMPORT/isolate then 
all of the words in that module will be local, even the SET 'word 
ones.
Izkata
3-Apr-2009
[12515]
So why not do something like this?
REBOL []
[
   process-image: func ....
]
................
image-processor: make object! load %image-processor.r
super-gfx: make object! load %super-gfx.r
image-processor/process-image foo
super-gfx/process-image foo


Static locals stay in memory, there's no extra steps to deal with 
conflicts, no special voodoo..  And, whenever process-image is called, 
it's obvious from where.
Anton
3-Apr-2009
[12516]
BrianH, it looks like R3 module system has the basics really well 
designed.
BrianH
3-Apr-2009
[12517x2]
Try this:
REBOL [type: module]
process-image: func ....

image-processor: import/only %image-processor.r
...
(that was to Izkata)
Pekr
3-Apr-2009
[12519]
First I thought that those refinements are not important, because 
- in fact you should specify such things in module header, but am 
I correct thinking, that refinements provide you kind of security? 
Do they override some internal module settings?
BrianH
3-Apr-2009
[12520]
Anton, I think it still needs some work, but it is usable as of alpha 
42 (when my DO fix went in). We can make it better later.
Maxim
3-Apr-2009
[12521]
anton, slim doesnt expose ANY words in the global context.  module 
interdependency is assured even if they each need each other's code. 
 and the infrastructure is embeded, where its the code LOADING the 
module which decides what to include.  by declaring words in a module, 
that uses another module, you don't even expose those words.

this is available in R2 for 5 years now.

slim/load 'module-name version 


module-name is searched for in search paths and must match header 
name, or its ignored.

slim/load/expose 'module version [a-function another-function]


you can even rename the funcs as you are exposing them to enforce 
code to cooperate:


slim/load/expose 'module version [[module-name my-own-name] [other-module-name 
my-other-name]]
Pekr
3-Apr-2009
[12522]
Brian - will modules allow some kind of protect mode? E.g. I want 
to have some func or word value to not be seen from external environment? 
So I don't want it to be accessible even by path notation?
Anton
3-Apr-2009
[12523]
Izkata, that's not a bad approach, but it has these problems:

1) LOADing a module is not quite the same as DOing it. DO sets up 
the current directory and system/script object correctly. LOAD doesn't, 
so the module might not be able to inspect itself and know about 
its location etc.

2) In trying to avoid setting words in the global context, you're 
setting words in the global context. Now you must use paths to get 
to what you want. This should be at the option of the user script. 
Obviously, you're exercising that option in your example. You could 
also do it this way:

 process-image1: get in context load %image-processor.r 'process-image
	process-image2: get in context load %super-gfx.r 'process-image
Maxim
3-Apr-2009
[12524]
for me the ONLY advantage of R3 modules is the fact that we seem 
to be able to enforce modules NOT to expose anything... since they 
are closed contexts.  I obviously cannot enforce this in R2, but 
all the management is aready there.
Pekr
3-Apr-2009
[12525]
... and also - we now have 'export functionality. Will we allow 'import, 
to import some values into the module?
BrianH
3-Apr-2009
[12526]
Pekr, the refinements override module header settings, and are used 
when you need to override default behavior, or when you don't quite 
trust the source.
Izkata
3-Apr-2009
[12527]
import/only - nice..  Looks like it's doing some weird things, but 
I'm not used to R3
BrianH
3-Apr-2009
[12528]
Access control will be added at the object! level - module! contexts 
are object! contexts.
Anton
3-Apr-2009
[12529]
Yes, import/isolate does look really nice.
Maxim
3-Apr-2009
[12530]
slim also has an auto-prefix option when you import words.  so as 
to make "collections" easy to differentiate, without having to rename 
each one separately.
BrianH
3-Apr-2009
[12531]
I wanted it by default, but the REBOL standard is to do the easy 
thing by default and the advanced thing with /only.
Maxim
3-Apr-2009
[12532]
there are a lot more tweaks like that... all working and being used 
for years by me... but everyone has always complained that REBOL 
has to stay simple... funny now that R3 comes out everyone is crying 
for features that have been available to all of you for years... 
 :-/
Anton
3-Apr-2009
[12533]
Maxim, ok, that's Slim, your software. I was just basically explaining 
to Steeve why I would strongly discourage using SET to export words.
Izkata
3-Apr-2009
[12534]
Anton - 1 just takes a do [] within the block, but I see what you 
mean, it is less intuitive