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

Maplist?

 [1/13] from: joel:neely:fedex at: 9-Sep-2001 3:18


Hi, Ric, and all, Ric Gagliardi wrote:
> Let me throw my variation in. I found I often used similar > anonymous functions in map-like situations, so I made a > variation that uses a block representing the body of the > function instead: > > every: func [
...
> ] > for example, > > >> every [a b] [1 2 3 4 5 6] [a + b] > == [3 7 11] >
Very nice!
> Similarly, I have 'keep: > > keep: func [
...
> ] > > >> keep a [1 2 3 4 5 6] [even? a] > == [2 4 6] >
Being of a more primitive mind-set, (and being somewhat partial to FUNC, from my LISP days) I've often used something like:
>> map: function [[throw] f [any-function!] b [block!] /all] [
[ result item] [ [ result: make block! length? b [ foreach val b [ [ item: f val [ if any [found? item all] [ [ append/only result item]] [ result] == [0 2 4]
>> map func [x] [x * x] [0 1 2 3 4 5]
== [0 1 4 9 16 25] The point of the /ALL refinement becomes clearer when used with another useful function:
>> ident: func [[throw] f [any-function!] x [any-type!]] [
[ if f x [x] [ ]
>> ident :even? 3
== none
>> ident :odd? 3
== 3 so that IDENT gives back either the second argument or NONE, depending on whether the second argument passes the filter test given by the first argument. Combining these two allows all sorts of on-the-fly filtering, such as
>> map func [x] [ident :even? x] [0 1 2 3 4 5]
== [0 2 4] or even (calculational-obscurity warning! ;-)
>> repeat rem [0 1 2 3 4] [
[ print [rem ":" [ map [ func [x] [ident func [x] [(x * x) // 5 = rem] x] [ [0 1 2 3 4 5 6 7 8 9 10] [ ]] 0 : 0 5 10 1 : 1 4 6 9 2 : 3 : 4 : 2 3 7 8 (For those not into number theory, this shows which natural numbers have squares with various residues mod 5. Yawn...) Seriously, the example is somewhat contrived, but was put together to show the power of FUNC combined with higher-order functions (as in Ladislav's very rich collection referenced earlier in this thread). -jn- -- ------------------------------------------------------------ Programming languages: compact, powerful, simple ... Pick any two! joel'dot'neely'at'fedex'dot'com

 [2/13] from: allenk:powerup:au at: 9-Sep-2001 23:52


----- Original Message ----- From: "Joel Neely" <[joel--neely--fedex--com]> To: <[rebol-list--rebol--com]> Sent: Sunday, September 09, 2001 6:18 PM Subject: [REBOL] Re: Maplist?
> Hi, Ric, and all, > Ric Gagliardi wrote:
<<quoted lines omitted: 13>>
> > > Very nice!
Is it intentional to set 'a and 'b in the global context too?
>> every [a b] [1 2 3 4 5 6] [a + b]
== [3 7 11]
>> a
== 5
>> b
== 6 Cheers, Allen K

 [3/13] from: ric:getorbital at: 10-Sep-2001 9:16


Thanks to both Allen and Joel for your pointers and counter examples. I think I'll take some time to either spiff up my mapping functions or exchange them altogether! -- Ric

 [4/13] from: dness:home at: 8-Sep-2001 16:54


I've look thru the documentation, but haven't had the answer to a very simple question jump out at me yet. Question: What converts ["123" "45667"] to [123 45667] or generalizing: How do I generate the block that is the result of applying some function to each element of an existing block (the classical Lisp `Maplist') function; perhaps more importantly, what documentation should I look at that would point me in the direction to solutions to this class of problems...

 [5/13] from: tim:johnsons-web at: 8-Sep-2001 14:23


On Sat, Sep 08, 2001 at 04:54:46PM -0400, David Ness wrote:
> I've look thru the documentation, but haven't had the answer to a very > simple question jump out at me yet. > > Question: > What converts ["123" "45667"] to [123 45667]
That's one question: here's one way to do it: ndx: 1 loop length? test[change at test ndx to-integer test/:ndx ndx: ndx + 1] == 3 ; the loop returns the final value of ndx
>> test ; let's look at test
== [123 45667] ;NOTE: 'test was changed
> or generalizing: > How do I generate the block that is the result of applying some > function to each element of an existing block (the classical > Lisp `Maplist') function;
This is a different case, if I understand your question. A second block would be created, and one would want to test the type of each member of the source block ; you might have something like this: dst: make block! length? test ; save memory reallocation internally ndx: 1 loop length? test[append dst to-integer test/:ndx ndx: ndx + 1]
>> test
== ["123" "4567"] ; is not changed
>> dst
== [123 4567] ; new block as a result
> perhaps more importantly, > what documentation should I look at that would point me in the > direction to solutions to this class of problems...
If I've understood you here, the core user's manual goes into series if great depth with charts and everything. PS: I wish I know more about lisp, I think a knowledge of lisp would add to the rebol "literature". Perhaps you're the one? HTH Tim
> -- > To unsubscribe from this list, please send an email to > [rebol-request--rebol--com] with "unsubscribe" in the > subject, without the quotes.
-- Tim Johnson <[tim--johnsons-web--com]> http://www.johnsons-web.com

 [6/13] from: dness:home at: 8-Sep-2001 17:52


Tim Johnson wrote:
> dst: make block! length? test ; save memory reallocation internally > ndx: 1
<<quoted lines omitted: 3>>
> >> dst > == [123 4567] ; new block as a result
Thanks. That's a help. I'll try it in my context. I should say, though, that I am surprised give how _direct_ REBOL is for solving so many problems that there isn't some sort of APPLY function that would take a F and an [L} and produce a [F(L)] IYSWIM.
> > perhaps more importantly, > > what documentation should I look at that would point me in the > > direction to solutions to this class of problems... > If I've understood you here, the core user's manual goes into series > if great depth with charts and everything.
Actually, since the `higher view' of what I want to do is so simple, I thought it was undoubtedly _there_ somewhere in the documentation and I had missed it. Your answer indicates that it isn't so simple, and thus isn't `there' in the docs for good reason.
> PS: I wish I know more about lisp, I think a knowledge of lisp > would add to the rebol "literature". > Perhaps you're the one?
Certainly not yet, but perhaps someday when I am more comfortable with REBOL. Thanks again.

 [7/13] from: larry:ecotope at: 8-Sep-2001 15:23


Hi David, Here is a short and simple version of MAP. I agree it would be nice if RT would implement a fast internal version of MAP. I find it extremely useful. map: func [f1 b /local out][ out: copy [] repeat el b [append/only out f1 :el] out ] Use it like this for a named function (note the : prefix is needed to delay full evaluation).
>> map :to-integer ["123" "45667"]
== [123 45667] If the named function needs a refinement switch you delay evaluation with a leading ' , like this:
>> map 'sine/radians [0 30 90]
== [0 -0.988031624092862 0.893996663600556] You can also use it with an anonymous function (defined on the fly) like this:
>> map func [x][x * x] [1 2 3]
== [1 4 9] I am very interested in the list operators of Scheme, Lisp, and modern functional languages like Haskell, Miranda, and Clean. I have implemented many of them in REBOL. So feel free to ask more on this topic. You might also benefit from Ladislav Mecir's highfun.r library: http://www.sweb.cz/LMecir/highfun.r Cheers -Larry

 [8/13] from: lmecir:mbox:vol:cz at: 9-Sep-2001 0:34


You can have a look at the http://www.sweb.cz/LMecir/highfun.r

 [9/13] from: dness:home at: 8-Sep-2001 18:46


Ladislav Mecir wrote:
> You can have a look at the http://www.sweb.cz/LMecir/highfun.r >
Thanks for the pointer. I think I've got my work cut out for me this evening... It looks _very_ interesting...

 [10/13] from: dness:home at: 8-Sep-2001 18:48


Larry Palmiter wrote:
> Hi David, > Here is a short and simple version of MAP. I agree it would be nice if RT
<<quoted lines omitted: 23>>
> Cheers > -Larry
Thanks. Another nice piece of code to (1) help me solve my problem; (2) teach me some more REBOL I appreciate your taking the trouble...

 [11/13] from: al:bri:xtra at: 9-Sep-2001 10:54


You could try: [ Rebol [ Name: 'Map Title: "Map" File: %"Map.r" Home: http://zen.scripterz.org/Rebol/Enhancements/ Author: "Andrew Martin" eMail: [Al--Bri--xtra--co--nz] Date: 17/November/2000 Version: 1.5.0 History: [ 1.5.0 {Removed 'throw-on-error to make it easier to track bugs down.} 1.4.0 {Modified to have any number of arguments per function} 1.3.0 {Modified to work with series! instead of block!.} 1.2.0 {unset! results are not returned - so allowing values to be filtered out.} 1.1.0 "Added /Only refinement." 1.0.0 "Original." ] Enhancement: 'Map Acknowledgements: [ "Joel Neely" "Ladislav" ] Purpose: {Maps or applies the function to all elements of the series.} Example: [ Map func [n [number!]] [n * n] [1 2 3] ;== [1 4 9] Map [1 2 3] func [n [number!]] [n * n] ;== [1 4 9] Map [1 2 3 4 5 6] func [a] [print [a]] ;1 ;2 ;3 ;4 ;5 ;6 ;== [] Map [1 2 3 4 5 6] func [a b] [print [a b]] ;1 2 ;3 4 ;5 6 ;== [] Map [1 2 3 4 5 6] func [a b c] [print [a b c]] ;1 2 3 ;4 5 6 ;== [] ] ] Arguments: function [f [any-function!]] [Arguments] [ Arguments: make block! 2 foreach Argument pick :f 1 [ if refinement? :Argument [ break ] append Arguments :Argument ] Arguments ] Map: function [ {Maps or applies the function to all elements of the series.} Arg1 [any-function! series!] Arg2 [any-function! series!] /Only "Inserts the result of the function as a series." ][ Result Results Function Series ][ any [ all [ any-function? :Arg1 series? :Arg2 (Function: :Arg1 Series: :Arg2 true) ] all [ any-function? :Arg2 series? :Arg1 (Function: :Arg2 Series: :Arg1 true) ] throw make error! reduce [ 'script 'cannot-use rejoin [ {"} mold 'Map " " mold type? :Arg1 {"} ] rejoin [ {"} mold type? :Arg2 {"} ] ] ] Results: make Series length? Series do reduce [ 'foreach Arguments :Function 'Series compose [ if not unset? set/any 'Result Function (Arguments :Function) [ either only [ insert/only tail Results :Result ][ insert tail Results :Result ] ] ] ] Results ] ] Andrew Martin ICQ: 26227169 http://zen.scripterz.org -><- ----- Original Message ----- From: "David Ness" <[DNess--Home--Com]> To: "Rebol List" <[rebol-list--rebol--com]> Sent: Sunday, September 09, 2001 8:54 AM Subject: [REBOL] Maplist?
> I've look thru the documentation, but haven't had the answer to a very > simple question jump out at me yet.
<<quoted lines omitted: 11>>
> [rebol-request--rebol--com] with "unsubscribe" in the > subject, without the quotes.
-- Attached file included as plaintext by Listar -- -- File: Map.r [ Rebol [ Name: 'Map Title: "Map" File: %"Map.r" Home: http://zen.scripterz.org/Rebol/Enhancements/ Author: "Andrew Martin" eMail: [Al--Bri--xtra--co--nz] Date: 17/November/2000 Version: 1.5.0 History: [ 1.5.0 {Removed 'throw-on-error to make it easier to track bugs down.} 1.4.0 {Modified to have any number of arguments per function} 1.3.0 {Modified to work with series! instead of block!.} 1.2.0 {unset! results are not returned - so allowing values to be filtered out.} 1.1.0 "Added /Only refinement." 1.0.0 "Original." ] Enhancement: 'Map Acknowledgements: [ "Joel Neely" "Ladislav" ] Purpose: {Maps or applies the function to all elements of the series.} Example: [ Map func [n [number!]] [n * n] [1 2 3] ;== [1 4 9] Map [1 2 3] func [n [number!]] [n * n] ;== [1 4 9] Map [1 2 3 4 5 6] func [a] [print [a]] ;1 ;2 ;3 ;4 ;5 ;6 ;== [] Map [1 2 3 4 5 6] func [a b] [print [a b]] ;1 2 ;3 4 ;5 6 ;== [] Map [1 2 3 4 5 6] func [a b c] [print [a b c]] ;1 2 3 ;4 5 6 ;== [] ] ] Arguments: function [f [any-function!]] [Arguments] [ Arguments: make block! 2 foreach Argument pick :f 1 [ if refinement? :Argument [ break ] append Arguments :Argument ] Arguments ] Map: function [ {Maps or applies the function to all elements of the series.} Arg1 [any-function! series!] Arg2 [any-function! series!] /Only "Inserts the result of the function as a series." ][ Result Results Function Series ][ any [ all [ any-function? :Arg1 series? :Arg2 (Function: :Arg1 Series: :Arg2 true) ] all [ any-function? :Arg2 series? :Arg1 (Function: :Arg2 Series: :Arg1 true) ] throw make error! reduce [ 'script 'cannot-use rejoin [ {"} mold 'Map " " mold type? :Arg1 {"} ] rejoin [ {"} mold type? :Arg2 {"} ] ] ] Results: make Series length? Series do reduce [ 'foreach Arguments :Function 'Series compose [ if not unset? set/any 'Result Function (Arguments :Function) [ either only [ insert/only tail Results :Result ][ insert tail Results :Result ] ] ] ] Results ] ]

 [12/13] from: ric:getorbital at: 8-Sep-2001 17:37


Let me throw my variation in. I found I often used similar anonymous functions in map-like situations, so I made a variation that uses a block representing the body of the function instead: every: func [ 'param [word! block!] list [series!] body [block!] /local result ][ result: copy [] either word? param [ forall list [ set param first list append result do body ] ][ while [not tail? list][ foreach item param [ set :item first list list: next list ] append result do body ] ] result ] for example,
>> every [a b] [1 2 3 4 5 6] [a + b]
== [3 7 11] Similarly, I have 'keep: keep: func [ 'param [word! block!] list [series!] body [block!] /only filter [block!] /local result ][ result: copy [] either word? param [ if only [make error! "Only works on param of type block!"] forall list [ set param first list if do body [append result get param] ] ][ while [not tail? list][ foreach item param [ set :item first list list: next list ] if do body [ foreach item param [ either only [ if find filter item [append result get item] ][ append result get item ] ] ] ] ] result ]
>> keep a [1 2 3 4 5 6] [even? a]
== [2 4 6] I use them all the time. BTW, any comments or critiques are welcome, as I am still on the learning curve. -- Ric

 [13/13] from: carl:cybercraft at: 9-Sep-2001 13:07


On 09-Sep-01, David Ness wrote:
> I've look thru the documentation, but haven't had the answer to a > very simple question jump out at me yet.
<<quoted lines omitted: 7>>
> what documentation should I look at that would point me in the > direction to solutions to this class of problems...
I see others have replied with more functional functions while I was working out the following rather limited one, but here it is anyway... convert: func [series [series!] apply [function! native! action!]][ head forall series [change series apply first series] ]
>> convert [1 2 3 "4" "5" "6"] :to-integer
== [1 2 3 4 5 6]
>> convert [1 2 3 "4" "5" "6"] :to-string
== ["1" "2" "3" "4" "5" "6"]
>> convert [1 2 3 a b c] :to-string
== ["1" "2" "3" "a" "b" "c"]
>> convert [1 2 3 a b c] :to-file
== [%1 %2 %3 %a %b %c]
>> convert ["123" "abc" "xyz"] :first
== [#"1" #"a" #"x"]
>> convert ["123" "abc" "xyz"] :reverse
== ["" "" ""]
>> convert convert ["123" "abc" "xyz"] :reverse :head
== ["321" "cba" "zyx"] The limitations are that you can't use a function's refinements (as with Larry's map function) or functions that require more than one argument, so the likes of append will return an error. -- Carl Read

Notes
  • Quoted lines have been omitted from some messages.
    View the message alone to see the lines that have been omitted