• Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

AltME groups: search

Help · search scripts · search articles · search mailing list

results summary

worldhits
r4wp1023
r3wp10555
total:11578

results window for this page: [start: 10101 end: 10200]

world-name: r3wp

Group: !REBOL3 GUI ... [web-public]
Pekr:
5-Jan-2010
BrianH: there are more changes planned, no? Like adding layers, etc. 
Henrik summed it up somewhere, maybe he can repost. And as far as 
I remember - the changes might influence your code, so I am not sure 
if it is good to do any GUI related work in recent VID state ...
Pekr:
6-Jan-2010
I just found Henrik's summary. I think it is the post I had in mind:
---------------------------------------------

Indeed VID3.4 is far from done. You can probably use it for a few 
things, like getting a name from a user in a text field or submit 
a very simple form, but not much more than that. To reiterate the 
state of the UI:

- No unicode yet in graphics (when Cyphre gets around to it).
- Resizing acts like a drunken sailor. (Carl)
- Skin is not published. (Me)
- Style tagging is not implemented. (Carl)
- Reasonable requesters are not yet implemented. (Carl or me)
- Layers are not yet implemented. (Carl)
- Guides are not yet implemented. (Carl)

- Better font rendering. We are not taking advantage of what AGG 
can do. (Cyphre again)
- Event system is from Gabriele's VID3. (Carl)
- Many features are untested, like drag&drop. (Me, I guess)
- Proper material management for skin. (Me).
- Many styles are not implemented, especially lists (Me).
- More elaborate animation engine (Carl or Me).
- Form dialect (Carl talked about this).
- More/better icon artwork (Me).


Plus, Maxim has some ideas for DRAW, to greatly speed up rendering, 
but I don't know if they can be implemented.


The overall design of the GUI engine is very good. Whenever a change 
or addition is made, you alter 3-5 lines of code in one place, and 
it works. I doubt the entire engine will be rewritten.


You won't see GUI bug reports in Curecode for a while. There could 
easily be 2-300 reports, once we get to that point.


My work regarding skins is rather big: I need to work out the basic 
styles first, so we have a reasonable way to build compound styles. 
These are being done using a very simple, but pixel accurate GUI 
using plain colored surfaces. This is easier for testing out, as 
draw blocks are small, but as Pekr likes to complain: They are not 
pretty to look at. Once the real skin goes into place, the draw blocks 
will grow a lot.


I would love to see a low-level GOB management dialect, like Gabriele's 
MakeGOB.
Pekr:
6-Jan-2010
Henrik and BrianH should agree upon what do we mean by "layers", 
as Henrik claims they need to be done, whereas BrianH claims we have 
them already :-)
Graham:
6-Jan-2010
Did you want to do that?  revise the viewtop sources?
Pekr:
8-Jan-2010
I digged following from Max in the past:
---------------------------------

My pet peeve about R3 view is that we still don't have access to 
the actual AGG elements directly within rebol.

We still have to go through a clumsy interface called draw dialect.

The dialect is fine (great actually) for initialisation, but after 
that, its not adapted to actual manipulation of what is going on 
inside, you have to go trough a rebol -> agg convertion stage at 
each refresh.

It's not the speed, it's the fact that it's complicated cause you 
have to create "virtual" draw components and then assemble them on 
the fly reducing blocks and stuff.
I'd love to be able to do:

a: draw [circle 30x30 15]
a/radius: 30
a/offset: 100x100
show a


If graphic elements where first class datatypes, we could completely 
ignore the gobs, and build real canvases, uber fast.

Another example, more appropriate:

; this draws a box...
draw [s: polygon 10x10  30x10 30x-30 10x-30]

; make it a house outline
insert at s/vertices 4 20x-40

; raise the "roof" 
s/vertices/4/y: -50


The problem is that to edit draw blocks, you have to create a slew 
of things before creating the draw block, then you have to store 
references to all of those things somewhere, everytime you want to 
add a "dynamic" attribute its pretty tedious.

The first-class gel datatype would allow AGG to edit its internals 
directly using binary C code through its accessors.  no need to go 
through rebol funcs and reducing blocks, etc.

The use of  "show a" above could intrinsincally know that it only 
needs to refresh the region that this element affects, just like 
all graphic cards do when evaluating the graphic pipe rendering.

So many things like flash games which become soooo heavy in AGG would 
be real-time and use much less CPU resouces.  in most games only 
a small part of the canvas really changes interactively.
Henrik:
8-Jan-2010
no, that doesn't have anything to do with GOBs. those are problems 
with DRAW. GOBs are about as small and lightweight as they can be. 
How they are used by the system is a different matter.
Graham:
15-Jan-2010
My first gui script http://rebol.wik.is/Rebol3/R3_GUI/Sendfax.r


I'd like to have the output from net-log appearing in the area .. 
but I can only get it do that once  and then nothing ...
Pavel:
19-Jan-2010
Hinting have mainly influence in rendering of "Stems" simplified 
it means all vertical lines will be the same width in my Ailal font 
I,L,M letters at some resolution. Having nothing to do with spaces 
between letters. Kerning is what is for inter letters spaces bussiness.
Henrik:
24-Jan-2010
Carl's original goal for the GUI was to make it so a child could 
use it. We should not deviate from that goal. That's part of what 
Rebrowse is meant to do. I don't want to risk a forking of the GUI 
work.
Henrik:
24-Jan-2010
Most of VID's serious issues come down to event handling (solvable 
now) and incompleteness (also solvable, just a bunch of hard work) 
and missing features, like keyboard navigation (already solved that). 
The VID extension kit makes VID much more scalable, simply by finishing 
the work that Carl set out to do. It's easier to write large apps 
because styles are more uniform, and you have more powerful features 
and adherence to face accessors, rather than relying on face hacking.


Building those features into V3.4 by default, and you have a killer 
UI system without sacrificing usability.
Pekr:
24-Jan-2010
Max - so what do you propose for the kernel, to not be 1.5 and 3, 
but 1, 2, 3? :-)
Ashley:
25-Jan-2010
I've spent a bit of time going over R3/View and believe it now has 
all the "building blocks" required to build a modern/fast gob! based 
GUI. The amazing thing is that these building blocks are the 10 natives 
that View adds [to Core]. They are:

	gob!
	caret-to-offset
	cursor
	draw
	effect
	map-event
	map-gob-offset
	offset-to-caret
	show
	size-text


With these 10 natives (gob! is actually a type!) we should be able 
to construct simple but powerfull gob!-based GUIs with a smaller 
mezz footprint than R2. My preliminary conversion of RebGUI to R3 
seems to take about 50% the code to do the same thing [compared to 
R2] ... very promising at first glance.


To get a feeling for how tight the code can be the next post is the 
entire [skeleton] source of a working gob!-based GUI.
Ashley:
25-Jan-2010
ctx-rebgui3: make object! [

	cursors: make object! [
		app-start: 32650
		hand: 32649
		help: 32651
		hourglass: 32650
		arrow: 32512
		cross: 32515
		i-shape: 32513
		no: 32648
		size-all: 32646
		size-nesw: 32643
		size-ns: 32645
		size-nwse: 32642
		size-we: 32644
		up-arrow: 32516
		wait: 32514
	]

	colors: make object! [
		page: white
		edit: white
		text: black
		true: leaf
		false: red
		link: blue
		theme: [165.217.246 0.105.207 0.55.155]
		outline: [207.207.207 160.160.160 112.112.112]
	]

	metrics: make object! [
		cell: 4
		gap: cell * 2
		line: cell * 5
		margin: cell * 4
		margin-size: as-pair margin margin
		radius: 2
	]

	;	Private functions

	set 'make-gob make function! [[

  spec [block!] ; offset, size and one or more attribute/value pairs
		/data object
		/local size text gob axis
	][
		size: spec/2
		if any [negative? size/x negative? size/y] [
			text: select spec 'text
			all [block? text text: first find text string!]

   size: 8x4 + size-text make gob! compose [size: 9999x9999 text: (text)]
			all [negative? spec/2/x spec/2/x: size/x]
			all [negative? spec/2/y spec/2/y: size/y]
		]
		gob: copy []
		;	attributes are (text, color, effect, image and draw)
		foreach [attribute value] spec [
			switch attribute [
				box [
					attribute: 'draw
					value: compose [
						pen (get value/1)
						line-width 1
						fill-pen (get value/2)
						box 0x0 (spec/2 - 1x1) (metrics/radius)
					]
				]
				pill [
					attribute: 'draw
					axis: either spec/2/x >= spec/2/y [2] [1]
					value: compose/deep [
						pen (colors/outline/3)
						line-width 1

      grad-pen linear (spec/2/:axis * .1) (spec/2/:axis * .9) (all [axis 
      = 2 90]) [(colors/outline/1) (white) (colors/outline/1)]
						box 0x0 (spec/2 - 1x1) (metrics/radius)
					]
				]
			]
			append gob reduce [attribute value]
		]
		spec: gob

  gob: make gob! compose [offset: spec/1 size: spec/2 (to set-word! 
  spec/3) spec/4 data: (make object! any [object copy []])]
		foreach [attribute value] skip spec 2 [

   append gob make gob! compose [offset: 0x0 size: spec/2 (to set-word! 
   attribute) value]
		]
		gob
	]]

	;	Public functions

	set 'display make function! [[
		title spec

  /local gob xy max-x max-y left-to-right? after-count after-limit 
  here arg append-widget widget last-widget word
		action
		handler
		size
		text
		color
	][
		xy: metrics/margin-size
		max-x: xy/x
		max-y: xy/y
		left-to-right?: true
		after-count: 1
		after-limit: 9999
		
		gob: make gob! compose [text: (title) data: (make object! [])]

		append-widget: make function! [[][
			unless widget [exit]
			unless handler [

    handler: compose/deep [on-down: make function! [[event][(action)]]]
			]
			append gob switch widget [
				bar [

     make-gob compose [(xy) (as-pair max-x - metrics/margin 1) color (colors/outline/3)]
				]
				button [
					all [none? size size: 15x5]

     make-gob/data compose/deep [(xy) (size * metrics/cell) pill none 
     text [center (text)]] handler
				]
				text [
					all [none? size size: 15x5]

     make-gob/data compose/only [(xy) (size * metrics/cell) color (white) 
     text (text)] handler
				]
			]
			last-widget: last gob/pane
			;	1st reverse item?
			unless left-to-right? [

    last-widget/offset/x: last-widget/offset/x - last-widget/size/x
			]
			xy: last-widget/offset
			;	max vertical size
			max-y: max max-y xy/y + last-widget/size/y
			;	horizontal pos adjustments
			all [
				left-to-right?
				xy/x: xy/x + last-widget/size/x
				max-x: max max-x xy/x
			]
			;	after limit reached?
			either after-count < after-limit [
				;	spacing

    xy/x: xy/x + either left-to-right? [metrics/gap] [negate metrics/gap]
				++ after-count
			] [
				xy: as-pair metrics/margin max-y + metrics/gap
				after-count: 1
			]
			all [:word set :word last-widget]
			word: widget: action: handler: size: text: color: none
		]]


  parse reduce/only spec [after bar button handler return reverse rich 
  text] [
			any [
				opt [here: set arg paren! (here/1: do arg) :here] [
					'return (
						append-widget
						xy: as-pair metrics/margin max-y + metrics/gap
						left-to-right?: true
						after-limit: 9999
					)
					| 'reverse (
						append-widget
						xy: as-pair max-x max-y + metrics/gap
						left-to-right?: false
						after-limit: 9999
					)
					| 'after set arg integer! (
						;	return unless this is first widget
						if widget [
							append-widget
							xy: as-pair metrics/margin max-y + metrics/gap
						]
						after-count: 1
						after-limit: arg
					)
					| 'handler set arg block! (handler: arg)
					| 'rich set arg block! (text: arg)
					| [set arg integer! | set arg pair!] (size: arg)
					| set arg string! (text: arg)
					| [set arg tuple! | set arg none!] (color: arg)
					| set arg block! (action: arg)
					| set arg set-word! (append-widget word: :arg)
					| set arg word! (append-widget widget: arg)
				]
			]
		]

		append-widget
		gob/size: metrics/margin-size + as-pair max-x max-y
		gob/offset: system/view/metrics/work-size - gob/size / 2
		append system/view/screen-gob gob
		show system/view/screen-gob
	]]

	set 'undisplay make function! [[gob][
		remove find system/view/screen-gob gob
		show system/view/screen-gob
	]]

	;	Start global GUI event handler

	active-gob: none
	system/view/event-port: open [scheme: 'event]

 system/view/event-port/awake: make function! [[event /local evt gob][
		evt: map-event event
		gob: evt/gob
		while [not object? gob/data] [gob: gob/parent]
		if all [event/type = 'move gob <> active-gob] [
			attempt [active-gob/data/on-away event]
			active-gob: gob
			attempt [active-gob/data/on-over event]
		]
		evt: to word! ajoin ['on- event/type]
		attempt [gob/data/:evt event]
	]]
]
Cyphre:
29-Jan-2010
Ashley, I can't see most of your problems when using r3-a96.exe
Please try:
do http://cyphre.mysteria.cz/tests/caret-test.r

You should see it works correcty.


The only problem I was able to repro is that the shortcuts b,i,u 
and nl aren't working...probably some 'regression' in newer builds 
as I remember it worked before.
Graham:
3-Feb-2010
I was just curious to see how Gab's systemm worked .. and I tried 
%test.r but 

>> do %test.r
Script: "Test vid" Version: none Date: none
Script: "REBOL View System Functions" Version: none Date: none
Script: "rewrite-tree function" Version: none Date: none

Script: "Simple dialect to create/resize gobs" Version: none Date: 
none

Script: "REBOL VID 3: Definition of FACE prototype object" Version: 
none Date: n
one
Script: "REBOL VID 3: Functions" Version: none Date: none
Script: "REBOL VID 3: Events Handling" Version: none Date: none
Script: "REBOL VID 3: Styles" Version: none Date: none
** Script error: cannot MAKE/TO map! from: none!

** Where: make either make handler parse parse-set-dialect make-styles 
catch eit
her either applier do catch either either applier do
** Near: make map! style-spec/options
Graham:
5-Feb-2010
Is there an easier way to do this than this?

    code-text-list: tight [

        about: "List of selectable text lines with scrollbar using a monospaced 
        font."
        facets: [
            max-size: 150x3000
        ]
        options: [
            list-data: [block!]
        ]
        content: [

            text-list-box :list-data :area-color options [ text-style: 'code 
            ]
            scroller
        ]
        actors: [
            on-init: [
                if select face 'reactors [
                    extend face/faces/1 'reactors face/reactors
                ]
            ]
            on-set: [
                set-face/list face/faces/1 arg
            ]
            on-get: [
                get-face face/faces/1
            ]
        ]
    ]
Ashley:
5-Feb-2010
OK, a meta-gob to recreate R2 functionality (given that a gob! can 
only do one thing)? I understand why layout was a "face factory" 
under V2, just thought we'd naturally move to a "gob! factory" approach 
with R3. I'm not being critical, just trying to understand why we 
still need the concept of faces under R3.
Henrik:
5-Feb-2010
Ashley, "just trying to understand why we still need the concept 
of faces under R3." - The role of faces in R3 are just what they 
were in R2, a collection of features and functions inside an object, 
but instead of the underlying View system being closed, they are 
now linked to a fixed set of GOBs, that we eventually can extend 
with all sorts of features. So:

R2:

Layout -> Face tree -> View

R3:

Layout -> Face tree -> GOBs -> View


Faces are what are generated by the layout. So the "face factory" 
is still needed and styles are the "molds" or prototypes. Within 
the face factory, the GOB factory exists. I would assume this separation 
makes HW acceleration or replacing GOBs with a different structure, 
much easier later. GOBs are redrawn using DRAW-FACE and that is handled 
inside the styles.


Styles use resources like fonts, colors, materials and standard draw 
blocks. This eventually helps skinning and abstracts these things 
away from the styles themselves.


The obscure FEEL object is replaced with a set of on-* actors that 
are run at specific times in specific sequences during runtime. They 
are more fine grained, so you can determine what you want to do, 
for example during various stages of face initialization.


The relationship between the layout dialect and faces is a bit different 
than under R2: you can't access the whole face in R3, only facets. 
For example the GOB itself, is not a facet and neither are internal 
states. So in order to change a deeper element of a style, you need 
to create a new style. This seems cumbersome, but is badly needed 
for large layouts, where we are semantically separating appearance 
from purpose. VID allowed this to be an organic mess. We may figure 
out a way to make creating derivative styles a bit easier.
Henrik:
5-Feb-2010
to be curious, what do you need the comment for?
Pekr:
5-Feb-2010
:-) So when the work on GUI is supposed to be restarted? Do we wait 
for its inclusion into HostKit section?
Pekr:
5-Feb-2010
I was just reading about upcoming new Facebook facelift ... and following 
the discussion I found out, that one person suggests very cool Facebook 
client done in Silverlight. I needed to download SL beta 4. Then 
I tried that mighty app. Guy, I can tell you - we can do it in View 
anyday. Its not any faster, any better, and I would really like to 
see the ugly code behind the app. My long time suggestion to popularise 
View is to wrap known services - gmail, FB, etc. E.g. especially 
on my Winmobile, ther's a FB client done by MS, and you can't even 
read more than 1 reaction to your post. I imediatelly can imagine 
Winmobile client in R3 :-)


Here's the screenshot - http://xidys.com/pekr/facebook-silverlight.jpg
Group: Core ... Discuss core issues [web-public]
Ladislav:
4-Nov-2010
Brian, in

http://www.curecode.org/rebol3/ticket.rsp?id=1744&cursor=2

you wrote: "We already have local THROW and RETURN"


If we do, I must have missed them, knowing only the global variants. 
Can you point me to them?
Sunanda:
5-Nov-2010
There may be better ways:
   first do to-path reduce ['a get 'd get 'e]
BrianH:
5-Nov-2010
You were focusing on localiity of where the code was written, and 
I was talking of locality in the code that the flow of execution 
goes through at runtime. For instance, #1744 makes it difficult for 
non-local-definition code to do man-in-the-middle attacks or spoofing, 
making it useful for secure mezzanine control flow functions. But 
#1518 prevents you from being able to pass THROW/name through unknown 
code at all, making it useless for making mezzanine control flow 
functions at all. Fixing #1518 is what we do to make #1743 possible, 
and once #1520 is implemented then the arms race will be over, everything 
else could be mezzanine or user-defined.
Ladislav:
14-Nov-2010
switch: func [
    "Selects a choice and evaluates what follows it." 
    value "Value to search for." 
    cases [block!] "Block of cases to search." 
    /default case "Default case if no others are found."
][
    either value: select cases value [do value] [
        either default [do case] [none]]
]

replace SELECT by SELECT/CASE
Anton:
17-Nov-2010
That functionality is pretty easy to by evaluating the word inside 
the condition block yourself.
eg.
	while [do cb] [...]

so I don't think it's really necessary.
Steeve:
3-Dec-2010
Nice challenge. To find the smallest mezz to do so
GrahamC:
3-Dec-2010
It's a GPL app to do drug prescribing and drug interactions .. I 
am just using their database
BrianH:
3-Dec-2010
Once the database is in memory you don't necessarily need to do set 
operations (SQL select). You can do iterative operations much more 
quickly.
GrahamC:
3-Dec-2010
so at present I think I generate all possible combinations and check 
to see if they're in the same set and if not do the sql query
BrianH:
10-Dec-2010
std::sort seems to do really well.
BrianH:
10-Dec-2010
Interesting. It's been a long time since I used C++ (there were no 
standard libraries then). It never occured to me that someone would 
use an unstable sort algorithm without checking first whether it 
would be safe to do so. I must have missed that in college.
Steeve:
15-Dec-2010
Searching for an optimal (small and fast) implementation of the following 
pattern.
* Swap two subsets inside a serie.

input 
	block:  [4  5  6   1 2] (5 values)
	Starting index of the 2nd subset inside the block: 4

Output:
	[ 1 2    4  5  6] 

Easy to do in plain Rebol right ?

But here's the trouble, It must be memory safe. You're not allowed 
to do any memory allocation.

You're can only swap values inside the block. And the number of swaps 
should be optimal.
(no sort, no parse, no copy/make/insert/append/change)
Sunanda:
15-Dec-2010
Just for starters.....This does it with 12 XORs (three per swap).

But the tricky bit may be pre-computing the from-list and to-list 
mapping

;; function to do the swap

swap-items: func [
   data [block!]
   from-list [block!]
   to-list [block!]
   /local
    ind1
    ind2
 ][
 for n 1 length? from-list 1 [
     ind1: from-list/:n
     ind2: to-list/:n
 
     data/:ind1: xor data/:ind1 data/:ind2
     data/:ind2: xor data/:ind1 data/:ind2
     data/:ind1: xor data/:ind1 data/:ind2
     ]
     return data
    ]

;; Sample run    
     block: [4 5 6 1 2]
     probe swap-items block [1 2  1 1] [3 4 5 2]
    [1 2 4 5 6]
Sunanda:
16-Dec-2010
I've written some very clunky code that I'd be ashamed to post as 
a solution.

But I can offer you an algorithm that acheives the effect in N-1 
swaps at most where 
N is the sum of the lengths of the two sequences.
It's the more-or-less same algorithm used by Andreas.

Here's how it works. Given these two sequences:
       a b c    1 2 3 4 5 6 7

Step1: cyclically rotate the longer sequence M times, where M is 
the difference in length of the sequences. So in this case, we rotate 
3 (7 - 4) times:
       a b c    4 5 6 7    1 2 3


Step2: swap the elements of the shorter sequence with the tail of 
the longer one:
       1 2 3    4 5 6 7    a b c
And it's done.


The cycling in place is the tricky part. It can be done, but my code 
is just too ugly to share :(

Andreas's bubble-to-front is an elegant approach to doing the cycling, 
but is not optimed to reduce the number of steps.

It's a managable sub-problem that is a challenge to solve, so I am 
sure someone can do better than me :)
Ladislav:
27-Dec-2010
In my opinion, to 'allow' INSERT, APPEND and CHANGE handle #[unset!] 
makes 'disallowing' POKE to do the same uncomfortable.
DideC:
8-Feb-2011
Rebol []

make-obj: func [
	"Créé un objet en sauvant son nom dedans."
	'name "Nom de l'objet à créer."
	obj "Objet de base à instancier."
	spec "extension de l'objet de base."
] [

 set name make obj append reduce [to-set-word 'obj-name to-string 
 name] spec
]


save-obj: func [
	"Sauvegarde un objet selon son propre nom."
	'obj "Objet à sauvegarder."
	/local name
] [

 name: any [all [word? obj  object? get obj  get in get obj 'obj-name] 
 join "objet" random 10000]
	save/all to-file join name ".r" get obj
]

load-obj: func [

 "Recharge un objet et l'intancie selon son propre nom s'il en a un."
	file "Nom du fichier à charger."
	/local obj
] [
	if exists? file [
		obj: load file
		probe bind next first obj obj
		probe get in obj 'list
		all [in obj 'obj-name  set to-word get in obj 'obj-name obj]
	]
	obj
]

task: make object! [
  list: copy []
  add: funct [t [block!]] [
    append list t
  ]
  save: does [
    save-obj self
  ]
  run: does [
    do list
  ]  
]

make-obj task1 task []
task1/add [a: 0 a: a + 1]
task1/add [print a]
task1/run
task1/save

task1: none

load-obj %task1.r
task1/run
Dockimbel:
8-Feb-2011
Anyway, binding information is lost during serialization (MOLD or 
MOLD/ALL), so if you want to get back bindings from serialized code, 
you need to manually ensure that the binding will be reconstructed 
as expected. That's achieved easily in your simple example using 
the SAVE / DO combination, but it can get much more complex in other 
cases and could require a lot of additional code.
Dockimbel:
8-Feb-2011
do load

 does not work with the serialized form (I tried it)?" I'm not sure 
 to understand what you mean there. SAVE/ALL uses MOLD/ALL to serialize 
 values, so binding information is not preserved. If you want to restore 
 correct binding in a object! serialized using /ALL format, you need 
 to write some code to walk through object's functions body blocks 
 and bind object's words explicitely using BIND.
Dockimbel:
8-Feb-2011
This would be similar to what MAKE does on an object's spec block! 
but a bit smarter as you need to dive into function! values (MAKE 
doesn't do that AFAICT). You need to see the distinction between 
"unevaluated code" (source form) and "evaluated code" (reduced form) 
to get a clear picture on this issue.
BrianH:
8-Feb-2011
Nested bindings are faked using a procedural process in REBOL. Serialized 
syntax is declarative, and there isn't a reference to the bindings 
in that syntax. It would be possible to make a serialized syntax 
that includes binding references, and the proposal to do that is 
called Rebin.
BrianH:
22-Feb-2011
All trailing pipe characters? Do you want to remove any other characters 
other than | ?
BrianH:
22-Feb-2011
So you might need to do a bit of tweaking for the R2 version, but 
it's a start.
BrianH:
23-Feb-2011
Here's a working version:

map-each: func [

 "Evaluates a block for each value(s) in a series and returns them 
 as a block."
	[throw catch]

 'word [word! block!] "Word or block of words to set each time (local)"
	data [block!] "The series to traverse"
	body [block!] "Block to evaluate each time"
	/into "Collect into a given series, rather than a new block"

 output [any-block! any-string!] "The series to output to" ; Not image!
	/local init len x
][
	; Shortcut return for empty data
	either empty? data [any [output make block! 0]] [
		; BIND/copy word and body
		word: either block? word [
			if empty? word [throw make error! [script invalid-arg []]]

   copy/deep word  ; /deep because word is rebound before errors checked
		] [reduce [word]]
		word: use word reduce [word]
		body: bind/copy body first word
		; Build init code
		init: none
		parse word [any [word! | x: set-word! (
			unless init [init: make block! 4]
			; Add [x: at data index] to init, and remove from word
			insert insert insert tail init first x [at data] index? x
			remove x
		) :x | x: skip (

   throw make error! reduce ['script 'expect-set [word! set-word!] type? 
   first x]
		)]]
		len: length? word ; Can be zero now (for advanced code tricks)
		; Create the output series if not specified
		unless into [output: make block! divide length? data max 1 len]
		; Process the data (which is not empty at this point)

  until [ ; Note: output: insert/only output needed for list! output
			set word data  do init

   unless unset? set/any 'x do body [output: insert/only output :x]
			tail? data: skip data len
		]
		; Return the output and clean up memory references
		also either into [output] [head output] (
			set [word data body output init x] none
		)
	]
]
Oldes:
7-Mar-2011
No.. it doesn't... it's possible to DO a script which has some sort 
of junk, but not LOAD.
james_nak:
11-Mar-2011
Sorry, about these delays. I was on on an online session.
So When I  use parse-xml+  on my xml string, I get the following:
[document [version none
        encoding none
        standalone none
        doctype none
        pubid none
        sysid none
        subset none

    ] [["TTL_Status" none ["^/^-" ["INPUT_TTLS" none ["^/^-^-" ["TTL_IN" 
    ["value" "0"] [{

^-^-^-} ["status" ["value" "1"] none] "^/^-^-"]] "^/^-^-" ["TTL_IN" 
["value" "1"] [{

^-^-^-} ["status" ["value" "1"] none] "^/^-^-"]] "^/^-"]] "^/^-" 
["OUTPUT_TTLS" none ["^/^-^-" ["TTL_OUT" ["value" "0"] [{

^-^-^-} ["status" ["value" "0"] none] "^/^-^-"]] "^/^-"]] "^/"]]]]

I know it's not that readable...

Then I run xml-to-object on that block and get:

o: xml-to-object  blk
where block is the output of parse-xml+ above.

probe o


[document: make object! [TTL_Status: make object! [INPUT_TTLS: make 
object! [TTL_IN: make block! reduce [

                    make object! [status: make object! [value?: "" value: "1"] value: 
                    "0"] make object! [status: make object! [value?: "" value
: "1"] value: "1"]

                ]] OUTPUT_TTLS: make object! [TTL_OUT: make object! [status: make 
                object! [value?: "" value: "0"] value: "0"]]] version: none
        encoding: none
        standalone: none
        doctype: none
        pubid: none
        sysid: none
        subset: none
    ]]


So this is where my ignorance leaves me. How do I make "o" into a 
an object where all the nested objects become real objects and don't 
remain as blocks?
Geocaching:
16-Mar-2011
Also, why the following code does not work:
>> rebcode: copy []
== []
>> append rebcode to-word "sine/radians"
== [sine/radians]
>> append rebcode 0.5
== [sine/radians 0.5]
>> do rebcode
** Script Error: sine/radians has no value
** Near: sine/radians 0.5
Geocaching:
16-Mar-2011
Thanks rebolek... interesting

But what do you mean with "It's possible to get your desired behaviour 
with #2, but it's slow."
Rebolek:
16-Mar-2011
I mean this:


>> dt [loop 1000 [c: copy [] append/only c 'sine/radians append c 
0.5 do c]]  
== 0:00:00.002512


>> dt [loop 1000 [c: copy [] append/only c load "sine/radians" append 
c 0.5 do c]]
== 0:00:00.035299


In second case, to convert from string! to path!, string must be 
loaded first and as you can see it's about 14x slower in this rough 
test.
Geocaching:
17-Mar-2011
Hello


Just a basic question: when creating or resetting a string! or a 
block!, should we do
a: ""
b: []
or is better to do
a: copy ""
b: copy []

I tend to do the second way...

Does it make a difference? If yes, which way is better.

Thanks
Geocaching:
17-Mar-2011
The bahaviour of my-code-a is confusing... What could be the point 
to do a: "" then?
Group: !REBOL3 Proposals ... For discussion of feature proposals [web-public]
BrianH:
3-Nov-2010
But SECURE doesn't protect from those kind of security issues anyways, 
so this may be not a problem that we have to worry about here. However, 
normally the security prompt will protect against this kind of thing, 
and the whole point of SECURE/do is to get rid of that prompt.
Maxim:
3-Nov-2010
though in most cases SECURE/do would be used to restrict what *your* 
code is allowed to access ...
BrianH:
3-Nov-2010
Full sandboxing would require running in a separate task, calling 
a script by IMPORT/no-lib/no-user/isolate instead of DO, and providing 
a whole set of safe words and wrapper functions for the script to 
use. But many aspects of the existing system are designed with this 
in mind.
BrianH:
3-Nov-2010
All you need to do to sandbox some code is isolate it and give it 
its own lib and user contexts.
BrianH:
3-Nov-2010
The SANDBOX function wouldn't then need to do anything custom to 
the user context that the script it is running is using. All it would 
need to do is create a safe system object, create an object that 
references that object using the 'system word, and set the lib and 
security settings to those provided as arguments to the SANDBOX function.
BrianH:
4-Nov-2010
#1521 would be better to do as a separate function (perhaps RECOVER).
PatrickP61:
4-Nov-2010
I would be just thrilled to see something like PROBE/SOLVE 

I have trouble "understanding" how to read rebol code.  I'm getting 
there, but still I make mistakes.  I would love to see a "step by 
step" breakdown of some rebol code.


I'll give you a good metaphor:   Remember Algebra, with parethasis 
and the steps you took to solve a problem:

( (a * 2) + (b / 3) ) / 5   Then you substituted for your variables 
step by step and solved the problem.  I'd love to have rebol do something 
like that.  So instead of one line like PROBE, you could get several 
lines, that show how the function was evaluated to arrive at the 
final result.  Maybe TRACE does this?


All in all, I'd like more debugging tools, or at least some expanded 
documentation on how to debug rebol code faster!  Thanks
Maxim:
8-Nov-2010
Pat, remember that you can replace the function building mezz code 
like funct and func.   though its not for novice users, since you 
do have the source when you 'SOURCE these builders, it can be quite 
easy to tweak them so they do a few things more...  like add a little 
break point at the end of each func and probe all the collected words, 
in FUNCT.


with a global word you could control if this tracing occurs, just 
by setting it to true or false, dynamically.
Andreas:
9-Nov-2010
That has nothing to do with inner functions.
Andreas:
9-Nov-2010
Of course, at this point you don't need to use an inner function 
at all, you just use bind + do.
Andreas:
9-Nov-2010
All you have to do is construct a correct inner function, instead 
of an erroneous one.
Andreas:
9-Nov-2010
Which is hypothetical as it is easy to show there are no such cases. 
So inner functions have nothing to do with it.
BrianH:
9-Nov-2010
So even the FOREACH workaround would be enough to prompt a change 
now. For that matter, the most recent module system rewrite was specifically 
for that reason. The new module system doesn't do anything that the 
pre-108 rewrite didn't do, but it is easier to use. Easy by default 
is the top priority.
BrianH:
9-Nov-2010
The only reason definitional-only might be chosen is because it is 
easier to understand than the other models. That alone might trump 
the places where it still doesn't work. I hope not, because the "option 
to not rebind RETURN and EXIT" is really simple to specify and much 
easier to do than the workarounds that you have to do if you don't 
have that option, workarounds like your BIND + DO, especially when 
you consider 'self issues that prevent you from using objects for 
this kind of thing (hence the FOREACH).
BrianH:
10-Nov-2010
You missed one thing: To make PARSE rules task-safe, we should be 
moving them into function blocks anyways. And recursion-safe, for 
some really obscure tricks that the new PARSE IF operation lets us 
do, but the task-safe thing will come up more often.
BrianH:
10-Nov-2010
So the "return from PARSE rules" thing will only be a problem for 
R2-style code. Once we do all the other tricks to make it R3-style, 
we get proper behavior for free :)
Ladislav:
11-Nov-2010
For an even more interesting thing - a definitional catch/throw pair 
(which can be ported to R2) see the Exception_proposals article. 
Advantage: you do not have to use any name, yet, only the right throw 
is caught.
Maxim:
11-Nov-2010
its just my bumbling appraisal so far, because it seems to me that 
you don't need to redefine and contextualize everything within your 
mezz code... but I do say I'm novice at this subject.  (I'm trying 
hard to completely "get" it/
Maxim:
11-Nov-2010
yes, but the error document tries to illustrate it too, and I didn''t 
see it as plainly as I do now.
BrianH:
11-Nov-2010
The reason we can get rid of dynamic returns in R3 is because the 
critical stuff that we used to do with dynamic returns in R2 is *necessarily* 
handled by dynamic breaks in R3, so dynamic returns are no big loss.
BrianH:
11-Nov-2010
Definitional returns or escapes rely on lexical scope. If you don't 
have lexical scope, you don't have the ability to do definitional. 
So what PARSE needs is for the top-level BREAK to be dynamic. And 
if one level is dynamic, we are better off with all levels being 
dynamic, at least for the same escape function. Same goes for definitional.
BrianH:
11-Nov-2010
Which is not the same as PARSE [(return)], but PARSE doesn't pay 
attention to the bindings of the keywords in its rules, just those 
of the rule names. And in the productions (parens) PARSE can't do 
any rebinding at all because it can't assume that BREAK is referring 
to the same function.
BrianH:
11-Nov-2010
It is becoming abundantly clear that there is more and more need 
for a comparison section that shows the strengths of dynamic vs. 
definitional, because people seem to not understand that there are 
ceratin classes of code and algorithms (parsing, for instance) that 
can't be expressed with strict lexical scoping. You are giving up 
a lot when you go definitional, so that better stuff not be as important 
in the context where you do it.
BrianH:
11-Nov-2010
And I can use those same proofs to apply to other algorithms with 
similar characteristics, and *know* that you gain some abilities 
with definitional scope, and lose others. This is why I know that 
Ladislav's DO-ALL is a loop, and so not wanting BREAK to apply to 
it is more of an opinion than something inherent in its nature. But 
that doesn't mean that the need for that is less.
BrianH:
11-Nov-2010
Please don't take my mentioning of downsides as being a statement 
of opinion or some kind of taking sides. I only mention them because 
they are real, and must be considered when picking a certain strategy. 
Both approaches have plusses and minuses. If you want to make a rational 
choice then you need to know the issues - otherwise you are just 
being a fanboy.


For instance, I picked the definitional side for returns, without 
the need for a fallback to dynamic, because of a rational evaluation 
of the algorithmic style of R3's functions. And it wasn't until I 
remembered that the tasking issues had already removed the advantages 
that dynamic scoping has over lexical scoping - we just can't do 
that stuff as much anymore, so it doesn't matter if we don't try. 
The same goes for loops, but to a lesser extent - loops aren't affected 
as much by tasking issues so we can still do code that would benefit 
from dynamic breaks, but it still might be a worthy tradeoff to avoid 
needing an option (since we have no such option). But for THROW, 
especially THROW/name, there are things that you can do with dynamic 
throw that you *can't* do with definitional, and those things would 
have great value, so it's a rational choice to make the tradeoff 
in favor of dynamic.
BrianH:
11-Nov-2010
Well it comes down to this: Functions are defined lexically. Though 
they are called dynamically, they aren't called until after they 
have already been bound, definitionally. But as a side effect of 
tasking, those bindings are stack-relative, and those stacks are 
task-local. But random blocks of code outside of functions are bound 
to object contexts, and those are *not* task-local. So that means 
that the old R2 practice of calling shared blocks of code is a really 
bad idea in R3 if any words are modified, unless there is some kind 
of locking or synchronization. This means that those blocks need 
to be moved into functions if their code is meant to be sharable, 
which means that at least as far as RETURN and EXIT are concerned, 
they can be considered lexically scoped. The advantage that we would 
get from being able to call a shared block of code and explicitly 
return in that block is moot, because we can't really do that much 
anymore. This means that we don't lose anything by switching to definitional 
code that we haven't already lost for other reasons. At least as 
far as functions are concerned, all task-safe code is definitional.


Loops are also defined lexically, more or less, and the rebinding 
ones are also task-safe because they are BIND/copy'd to a selfless 
object context that is only used for that one call and thrown away 
afterwards. And most calls to loops are task-safe anyways because 
they are contained in functions. However, the LOOP, FORALL, FORSKIP 
and WHILE loops do not rebind at the moment. We actually prefer to 
use those particular loops sometimes in R3 code because they can 
be more efficient than *EACH and REPEAT, because they don't have 
that BIND/copy overhead. Other times we prefer to use *EACH or REPEAT, 
in case particular loop fits better, or has high-enough repetitions 
and enough word references that the 27% overhead for stack-local 
word reference is enough to be more than the once-per-loop BIND/copy 
overhead. Since you don't have to move blocks into *loops* to make 
them task-safe, you can use blocks referred to by word to hold code 
that would be shared between different bits of code in the same function. 
This is called manual common subexpression elimination (CSE), and 
is a common optimization trick in advanced REBOL code, because we 
have to hand-optimize REBOL using tricks that the compiler would 
do for us if we were using a compiled language. Also, PARSE rules 
are often called from loops, and they are frequently (and in specific 
cases necessarily) referred to by word instead of lexically nested; 
most of the time these rules can be quite large, maximizing BIND/copy 
overhead, so you definitely don't want to put the extensive ones 
in a FOREACH or a closure.

Switching to definitional break would have three real downsides:

* Every loop would need to BIND/copy, every time the loop is called, 
including the loops that we were explicitly using because they *don't* 
BIND/copy.

* Code that is not nested in the main loop block would not be able 
to break from that loop. And code that is nested in the main loop 
would BIND/copy.

* We can in theory catch unwinds, run some recovery code, and send 
them on their way (hopefully only in native code, see #1521). Definitional 
escapes might be hard or impossible to catch in this way, depending 
on how they are implemented, and that would mean that you couldn't 
recover from breaks anymore.


The upside to definitional break would be that you could skip past 
a loop or two if you wanted to, something you currently can't do. 
Another way to accomplish that would be to add /name options to all 
the loop functions, and that wouldn't have the BIND/copy overhead. 
Or to use THROW or THROW/name.


The situation with THROW is similar to that of the non-binding loops, 
but more so, still task-safe because of functions. But CATCH and 
THROW are typically the most useful in two scenarios:

* Escaping through a lot of levels that would catch dynamic breaks 
or returns.

* Premade custom escape functions that might need to enforce specific 
semantics.


Both of these uses can cause a great deal of difficulty if we switched 
to definitional throw. In the first case, the code is often either 
broken into different functions (and thus not nested), or all dumped 
into a very large set of nested code that we wouldn't want to BIND/copy. 
Remember, the more levels we want to throw past, the more code that 
goes into implementing those levels. In the second case definitional 
throw would usually not work at all because the CATCH and the THROW 
would contained in different functions, and the code that calls the 
function wrapping the THROW would not be nested inside the CATCH. 
So you would either need to rebind every bit of code that called 
the THROW, or the definitional THROW would need to be passed to the 
code that wants to call it like a continuation (similar concept). 
Either way would be really awkward.


On the plus side of dynamic (whatever), at least it's easy to catch 
an unwind for debugging, testing or recovery purposes. For that matter, 
the main advantage of using THROW/name as the basic operation that 
developers can use to make custom dynamic escape functions is that 
we can build in a standard way to catch it and that will work for 
every custom escape that is built with it. The end to the arms race 
of break-through and catch.
BrianH:
11-Nov-2010
Definitional (whatever) depends on a BIND to do its work, deep, usually 
BIND/copy. And that only works on words that are physically in the 
blocks that you bind, or in blocks that are nested in those blocks, 
etc. Another block that is outside the block you are binding and 
referred to by name won't be bound. That is the limit of the definitional 
approach.
BrianH:
12-Nov-2010
Yes, but lexical scope has nothing to do with lexical keywords.
Ladislav:
12-Nov-2010
I do understand that "blocks don't have to be nested", but that does 
not relate to the fact, that break in parse behaves lexically
Ladislav:
12-Nov-2010
{very novice question - parse [break] is not the same as parse [(break)] 
internally?} - correct, they are two completely unrelated constructs, 
the latter being "foreing" to parse, related to the do dialect, in 
fact
Ladislav:
12-Nov-2010
... I know that Ladislav's DO-ALL is a loop, and so not wanting BREAK 
to apply to it is more of an opinion than something inherent in its 
nature.

 - I was afraid, that the DO-ALL was not a fortunate choice! My original 
 problem with the property illustrated by DO-ALL occurred when I Implemented 
 my PIF (now called CASE for the newcomers), which was not meant to 
 catch any breaks, as is immediately obvious.
BrianH:
12-Nov-2010
Debug/test needs a standard way to catch everything, but afaict there 
is no way to do so with definitional return. The same would go for 
the others if they were definitional, but that is less likely for 
the reasons given above. We might just have to live with not being 
able to catch definitional return - it should be easy to control 
the test environment so its return functions don't propagate into 
the test code, so that probably won't be a problem, at least for 
returns.
BrianH:
12-Nov-2010
Yup. But I was mostly referring to the standard way the loop functions 
are used. Most loops are mostly made up of nested blocks and such, 
with very little direct DO calls to other blocks by name.
BrianH:
12-Nov-2010
DO (or IF, or ALL, ...) of a block by name tends to only show up 
in advanced code. That code tends to be critical, and we usually 
can't afford to make it non-working, but not many people do that 
level of hand-optimization of their code, mostly because their code 
isn't that speed or size critical, or they don't know how (or they 
don't like that technique). On the other hand, PARSE rules called 
from loops are often referred to by name and are moved physically 
outside of the loops that call them for really good reasons, some 
of which I mentioned above.
BrianH:
12-Nov-2010
Carl uses the manual CSE trick a lot - I learned to do so from him 
:)
BrianH:
12-Nov-2010
You don't lose anything that you haven't already lost for other reasons, 
and it is possible (in native code) to build in acceptable workarounds 
for its weaknesses, so there's no significant downside to definitional 
return (except the work Carl would have to do to implement it).
Ladislav:
12-Nov-2010
In the case of BREAK (I mean the one used in the DO dialect now), 
the situation is 50:50, since loops would be bound once, done many 
times anyway, making any slow-down % much smaller, and due to the 
fact, that some loops (as you mentioned earlier too), need to bind 
their bodies anyway
BrianH:
12-Nov-2010
I don't know how much R3 code you've had to optimize, but I've had 
to optimize it a lot. That BIND/copy overhead is significant. It 
takes a *lot* of loop reps to balance it out, more than most code 
needs to do by something like an order of magnitude. It's not 50:50.
BrianH:
12-Nov-2010
Carl has mused that there might be a faster way to do BIND/copy in 
loops. It would be welcomed.
Ladislav:
12-Nov-2010
Well, I do not hesitate to use Foreach or Repeat where appropriate
Ladislav:
13-Nov-2010
To make myself clear, I do not object against the word 'self being 
protected..., the only thing I mind about is the "keywordness" of 
the word.
BrianH:
13-Nov-2010
Really awkward to do so though, and you can't just see the structure 
in source so it is harder for many people to understand.
BrianH:
13-Nov-2010
We could really use a native LET or SELFLESS - either would do, actually, 
and could be used to implement the other.
Henrik:
14-Nov-2010
Well, I think it would be clearer to see it applied in loops and 
using multiple values. As it is shown there, USE and DO FUNC are 
clearer to me. It may be very useful.
Ladislav:
14-Nov-2010
As far as the DO FUNC examples go, they are just equivalent to the 
LET examples, as is quite obvious. The distinctions are rather small, 
like the fact, that you do not need to create a function and then 
call DO
Ladislav:
14-Nov-2010
less overhead for the user (does not have to call DO), less overhead 
for the interpreter (does not have to create the function), and a 
couple more quirks like RETURN and EXIT handling
Maxim:
15-Nov-2010
on the question, why do we really need self:


self is very usefull when you use objects within code, because there 
can often be binding clashes.   self assures one that a parameter 
is always from the context and not from the function.

self.x: x


has occured pretty often for me.  its also very usefull when you 
need to return the context from which a function was bound.  
I also use it to do indirection: 

obj: self
context [
	parent: obj
]


remove self, and we can't say that REBOL has objects anymore.  many 
things will become really complicated for no reason.
Andreas:
25-Nov-2010
A more direct way to cause a basic error might be very useful. Currently, 
if you don't want/need to give any thought what an appropriate error 
might be you'll do:

    cause-error 'user 'message "error message"


Which is a lot longer than `make error! "error message"` was in R2. 
Having written the above in R3 a lot, recently, I now use a CAUSE-USER-ERROR 
shorthand, which might be nice to have in general:

    cause-user-error "error message"
BrianH:
25-Nov-2010
You can still do this in R3: do make error! "error message"

The only difference from R2 is that you have to DO the error to trigger 
it.
10101 / 1157812345...100101[102] 103104...112113114115116