Bidirectional value mapping.
[1/13] from: bga::bug-br::org::br at: 3-Nov-2003 15:07
Hello.
I have 2 values that would be mapped to each other. What I need to do is
to be able to find the first valeu by searching for the ceond and locate
the second by searching for the first. I did come up with solutions to
that but I am not satisfied with any of the solutions. Is there a standard
Rebol-Way ofr doing that? The best option would be a way that would not
result in data duplication.
-Bruno
[2/13] from: maximo:meteorstudios at: 3-Nov-2003 11:52
liquid.
that is its main purpose. it is also linked to vid via liquid-vid.
development has slown down for a few weeks, but it'll pick up.
http://www.rebol.it/~steel
a working version and some documentation can be found here: http://www.rebol.it/~steel
for an understanding of liquid itself, you should test out liquid-vid. 90% of it is
a direct extension of liquid (concept, nomenclature, functioning, etc).
you can validate data localy to each but the actual storage is shared. if you really
want to could create a container, which actually stores a copy of the value locally to
an object (in an altered state?).
HTH
ciao!
-MAx
-------------
Steel project coordinator
http://www.rebol.it/~steel
[3/13] from: patrick:philipot:laposte at: 3-Nov-2003 18:33
Hi Bruno,
You can use 'select with a little trick
>> firstvalue: 1
== 1
>> secondvalue: 2
== 2
>> searchblock: reduce [firstvalue secondvalue firstvalue]
== [1 2 1]
>> select searchblock firstvalue
== 2
>> select searchblock secondvalue
== 1
>> select searchblock firstvalue
== 2
>> select searchblock secondvalue
== 1
Regards
Patrick
[4/13] from: apwing:zonnet:nl at: 3-Nov-2003 18:57
Hi bruno,
do you mean something like the ALIAS function? http://www.rebol.com/docs/words/walias.html
If not, can you supply some code, an example?
Met vriendelijke groet / with kind regards,
Arie van Wingerden
http://home.zonnet.nl/rebolution
ICQ 343101686
----- Original Message -----
From: Bruno G. Albuquerque
To: [rebol-list--rebol--com]
Sent: Monday, November 03, 2003 6:07 PM
Subject: [REBOL] Bidirectional value mapping.
Hello.
I have 2 values that would be mapped to each other. What I need to do is
to be able to find the first valeu by searching for the ceond and locate
the second by searching for the first. I did come up with solutions to
that but I am not satisfied with any of the solutions. Is there a standard
Rebol-Way ofr doing that? The best option would be a way that would not
result in data duplication.
-Bruno
[5/13] from: bga:bug-br at: 3-Nov-2003 17:12
Hello Arie.
Thanks but this is not what I was looking for. Patrick nailed it though
(although his solution results in data duplication). See my previous
email.
-Bruno
Arie van Wingerden disse:
[6/13] from: bga:bug-br at: 3-Nov-2003 17:11
Hello Patrick.
Thanks! This works great (although there is data duplication). It even
works in a case like this:
>> firstvalue:1
== 1
>> secondvalue: 2
== 2
>> thirdvalue: 3
== 3
>> fourthvalue: 4
== 4
>> test: [ 1 2 1 3 4 3 ]
== [1 2 1 3 4 3]
>> select teste 1
== 2
>> select teste 2
== 1
>> select teste 3
== 4
>> select teste 4
== 3
It looks select just returns after the first occurence of the data being
searched with, in this case, is a good thing.
-Bruno
[7/13] from: joel:neely:fedex at: 3-Nov-2003 12:56
Hi, Bruno,
I know of no way to avoid some duplication. See below.
Bruno G. Albuquerque wrote:
> I have 2 values that would be mapped to each other. What I need to do is
> to be able to find the first valeu by searching for the ceond and locate
> the second by searching for the first. I did come up with solutions to
> that but I am not satisfied with any of the solutions. Is there a standard
> Rebol-Way ofr doing that? The best option would be a way that would not
> result in data duplication.
>
The answer somewhat depends on details of your problem; if "forward"
and "reverse" mappings are distinct (as in translating between host
names and IP addresses, or encoding and decoding with a non-symmetric
encryption scheme) then the simplest thing to do is keep both maps
as separate blocks (or hashes):
>> roman2number: ["i" 1 "v" 5 "x" 10 "l" 50 "c" 100]
== ["i" 1 "v" 5 "x" 10 "l" 50 "c" 100]
>> number2roman: [1 "i" 5 "v" 10 "x" 50 "l" 100 "c"]
== [1 "i" 5 "v" 10 "x" 50 "l" 100 "c"]
>> select roman2number "x"
== 10
>> select number2roman 10
== "x"
If you know which "way" you're mapping, you just select the appropriate
map. (Of course, it's easy to write a function that would take one of
the above and give the other, so you don't have to create both by hand.)
NOTE!!! That last sentence is only true if the mapping is an invertable
function!!! If, instead, you have a many-to-one (e.g. letters to the
words "consonant" or "vowel") of course there's no way to invert. I
assume you know that, but want to include that warning for completeness.
The other (perhaps slightly more "REBOLish") way to do this is to inter-
leave the forward and reverse mapping values as follows:
>> roman-numerals: [
"i" 1 "i" "v" 5 "v" "x" 10 "x" "l" 50 "l" "c" 100 "c"
]
== ["i" 1 "i" "v" 5 "v" "x" 10 "x" "l" 50 "l" "c" 100 "c"]
>> select roman-numerals "x"
== 10
>> select roman-numerals 10
== "x"
This works nicely for such things as ROT13, which is a self-inverse
mapping (and again, you can write a utility function that would take
e.g. ROMAN2NUMBER above and give you the interleaved ROMAN-NUMERALS).
However THIS DOES NOT WORK IN GENERAL if the domain and range of your
mapping overlap. As a simple example, consider the trivial example of
rotating among three elements:
forward: ["a" "b" "c" "a"]
reverse: ["c" "b" "a" "c"]
Since "a" maps to "b" going forward, but "b" maps to "c" going forward,
then both forward and reverse mappings can't be combined into a single
block/hash. To see why this is true, consider what would have to follow
b
in the combined series!
Unless you know you have a self-inverse mapping and you consider speed
soooooo important that you'll sacrifice readability for performance,
I recommend using distinct forward/reverse mappings (with a helper to
construct the inverted one). It'll be easier to read anyway!
-jn-
--
----------------------------------------------------------------------
Joel Neely joelDOTneelyATfedexDOTcom 901-263-4446
Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1
[8/13] from: bga:bug-br at: 3-Nov-2003 18:01
Hello Joel.
That's what I call a complete explanation. Thanks!
I decided to use the interleaved values option. The reason I need
something like what I described is that I am creating a HTTP Proxy using
Rebol (that will eventually evolve into an HTTP Tunnel application). The
mapping is used to map the incoming port to the outgoing one as I have
data arriving and leaving from both ports so I need a way to determine
where I have to send the data I just received in a specific port.
BTW, the reason I am doing this HTTP proxy is because I need NTLM
authentication. I already have all the NTLM stuff working (including DES
encryption by loading the OpenSSL library and using it) under Rebol and I
am now doing the proxy itself.
Joel Neely disse:
[9/13] from: rotenca:telvia:it at: 3-Nov-2003 21:04
Hello.
> I have 2 values that would be mapped to each other. What I need to do is
> to be able to find the first valeu by searching for the ceond and locate
> the second by searching for the first. I did come up with solutions to
> that but I am not satisfied with any of the solutions. Is there a standard
> Rebol-Way ofr doing that? The best option would be a way that would not
> result in data duplication.
If values are in a block:
>> select [a 1] 'a
== 1
>> first back find [a 1] 1
== a
the last can be wrapped by a function which tests the existence of the value.
bselect: func [blk value][
if blk: find blk value [pick blk -1]
]
---
Ciao
Romano
[10/13] from: Christian:Ensel:GMX at: 3-Nov-2003 21:10
Hi Bruno,
doing it in the SELECT-way is nice but you should consider using it with the
/SKIP-refinement. Without this you may end up with surprising results if one
value may occur in value-1 and value-2 position as in
;------------------------------------
>> that's-life: [cats birds cats birds insects birds]
>> who-hunts?: func ['animal] [select that's-life animal]
>> who-hunts? birds
== cats
>> who-hunts? insects
== birds
>> prey-of?: func ['animal] [select that's-life animal]
>> prey-of? cats
== birds
>> prey-of? birds
== cats ; OOPS!
;------------------------------------
The following design doesn't suffer from this difficulty and avoids
duplication of values, too, at the cost of a little bit more maintenance
work:
;------------------------------------
color-names: [red green blue]
color-values: [255.0.0 0.255.0 0.0.255]
select-color-by-name: func [name [word!] /local color] [
if color: find color-names name [pick color-values index? color]
]
select-color-by-values: func [value [tuple!] /local color] [
if color: find color-values value [pick color-names index? color]
]
append-color: func [name [word!] value [tuple!]] [
append color-names color
append color-values color
]
remove-color: func [name [word!] value [tuple!]] [
remove find color-names name
remove find color-values value
]
;------------------------------------
A lot of improvements can be made to this, especially the REMOVE-COLOR is
somewhat bad designed in respect to data-integrity (try REMOVE-COLOR RED
0.255.0 - Hey, I'm color-blind ;-)
But what I like about the design this approach that it is easily expandable in
cases you have to deal with tuples of data of length greater than just 2.
HTH,
Christian
[11/13] from: maximo:meteorstudios at: 3-Nov-2003 16:07
Hi Bruno,
I'm sorry If I have induced you into error, but I did not understand the question in
the proper way...
If you want to map a series of values to-from, then liquid isn't really the thing to
use... I thought you meant to keep a synchronisation between to entities... so that
a change in one repercutes as a change to the other...
But, just using select a reverse on a series, makes it map one value to another, if you
want to map the other way, you need to use reverse (but, of course, you need to know
the direction of the search):
list: ["a" 1 "b" 2 "c" 3]
select list "b"
==2
select (head reverse copy list) 2
==
b
note that the parentheses aren't necessary, I just added them to increase readability.
I've read that they can affect performance, so they should be removed when used in real
code.
HTH
-MAx
---
You can either be part of the problem or part of the solution, but in the end, being
part of the problem is much more fun.
[12/13] from: g:santilli:tiscalinet:it at: 4-Nov-2003 10:53
Hi Bruno,
On Monday, November 3, 2003, 9:01:44 PM, you wrote:
BGA> I decided to use the interleaved values option. The reason I need
BGA> something like what I described is that I am creating a HTTP Proxy using
BGA> Rebol (that will eventually evolve into an HTTP Tunnel application). The
BGA> mapping is used to map the incoming port to the outgoing one as I have
BGA> data arriving and leaving from both ports so I need a way to determine
BGA> where I have to send the data I just received in a specific port.
You could have the other port in port/userdata. I.e.:
; someone connects
in-port: first listen
; ...
; you open your port
out-port: open ...
; set up the relationship
out-port/userdata: in-port
in-port/userdata: out-port
; ...
; now if you receved data on PORT
insert port/userdata copy port
; the above works for both ports
This is just to give you some ideas.
Regards,
Gabriele.
--
Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer
Amiga Group Italia sez. L'Aquila --- SOON: http://www.rebol.it/
[13/13] from: robert:muench:robertmuench at: 8-Nov-2003 18:25
On Mon, 3 Nov 2003 18:01:44 -0200 (BRST), Bruno G. Albuquerque
<[bga--bug-br--org--br]> wrote:
> BTW, the reason I am doing this HTTP proxy is because I need NTLM
> authentication. I already have all the NTLM stuff working (including DES
> encryption by loading the OpenSSL library and using it) under Rebol and I
> am now doing the proxy itself.
Hi, NTLM authentification? That's very interesting. I once had a Python
script that worked the same way as a localhost proxy to give
non-NTLM-aware applications access to it. IIRC the Python solution didn't
required OpenSSL, it was all done in Python. One other thing comes to
mind: Do you know http://www.htthost.com ? Robert