Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

[REBOL] Re: Is there a REBOL construct similar to the "map" word as usedin Logo

From: joel:neely:fedex at: 29-Jun-2002 8:19

(I sent something similar to this yesterday, but it never showed up on the list. If it ever does emerge, please forgive the duplication.) Hi, Gerard, As you can tell, this has been kicked around before... ;-) Gerard Cote wrote:
> Now is another question relative to the word "map" I already > used in Logo for working on agregates - that is data collections > - and doesn't seem to exist per se in the same form under REBOL. > > May be I don't really need it for solving the following case but > nevertheless I would like to get some advice about something > similar in REBOL if anyone exists that is different than the two > ones I found myself when using the "forall" and "foreach" words. >
I've observed a number of cases where features from other languages aren't built into REBOL, but are really easy to implement oneself. Since functions are first-class values in REBOL, you can build all sorts of interesting control and higher-order functions. Here's another variation from the past: map: func [ [throw] f [any-function!] b [block!] /all /local result item ][ result: make block! length? b foreach val b [ if any [found? item: f val all] [ append/only result item ] ] result ] Which does the basics:
>> map func [x] [x * x] [1 2 3 4 5 6]
== [1 4 9 16 25 36] The point of the /ALL refinement is that we can create filters by using a simple helper function: ident: func [[throw] f [any-function!] x [any-type!]] [ if f x [x] ] which evaluates either to the second argument or to NONE, depending on whether the second argument passes the test specified in the first argument.
>> ident :even? 3
== none
>> ident :odd? 3
== 3 With both of these in hand, one can either map a test across a collection and get the pass fail results:
>> map :even? [1 2 3 4 5 6]
== [false true false true false true] or use the test to select the desired elements
>> map func [x] [ident :even? x] [1 2 3 4 5 6]
== [2 4 6]
> >> print initials [George Harrison] > [G H] > >> map :first ["George" "Harrison"]
== [#"G" #"H"]
> Other functional languages also frequently use the term "anonymous > function" for something that looks a bit related to the question- > marked items in the following examples but it seems that's all > there is to it, as far as I know of. >
Reread the documentation on FUNC. It is a built-in function that produces a function value, which (as I mentioned above) is a first- class type in REBOL, meaning that it can be assigned, passed as an argument, or returned as the result of an evaluation.
> ? show map [? * ?] [2 3 4 5] <-- Applies the > product of an item with itself to each member of > [4 9 16 25] the > second list. >
As above:
>> map func [x] [x * x] [2 3 4 5]
== [4 9 16 25]
> ? show (map [word ?1 ?2 ?1] [a b c] [d e f]) <--- this means create > words that are combinations of 3 letters > [ada beb cfc] > the first and third ones being taken from the first list while > the second onecomes from the second list. >
There are two parts to this one; - just use FUNC for the "anonymous function" to be applied, - due to the way REBOL handles arguments, I'd probably code the multiple-arguments version separately. Constructing a collection of arguments by transposing/slicing from a collection of argument lists could be done this way: mapn: func [ [throw] f [any-function!] b [block!] /local n result ][ n: 0 foreach bb b [n: max n length? bb] result: make block! n loop n [ append/only result do join [f] map :first b b: map :next b ] result ] which behaves as follows:
>> mapn :+ [[1 2 3 4][10 20 30 40]]
== [11 22 33 44] Then your sample problem could be represented in REBOL (among many other ways! ;-) as:
>> mapn func [a b] [rejoin [a b a]] [["a" "b" "c"] ["d" "e" "f"]]
== ["ada" "beb" "cfc"] Hope this helps! -jn- -- ; Joel Neely joeldotneelyatfedexdotcom REBOL [] do [ do func [s] [ foreach [a b] s [prin b] ] sort/skip do function [s] [t] [ t: "" foreach [a b] s [repend t [b a]] t ] { | e s m!zauafBpcvekexEohthjJakwLrngohOqrlryRnsctdtiub} 2 ]