Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Nesting functional commands

62 views
Skip to first unread message

Erin Noel

unread,
Sep 1, 2009, 3:51:26 AM9/1/09
to
Hi,

So how would you go about nesting a functional command inside of another
functional command? For example, say A={1,2,3,4}, then 3*#&/@A = {3,6,9,12}.
No problem. But then what if, within that vector {3,6,9,12}, I wanted to use
the Select command to choose elements less than, say 7. The command
Select[3*#&/@A,#<7&] doesn't work because, as far as I can tell, Mathematica
doesn't know which "#" belongs to Select and which "#" belongs to the &/@
mapping over A. I know that I could define 3*#&/@A as a new variable and
then use that new variable in the Select command, but is there any way to
nest multiple commands in this way?

Thanks a lot in advance,
Erin


Patrick Scheibe

unread,
Sep 2, 2009, 3:58:52 AM9/2/09
to
Hi,

in this case it is easy. Just "say" how you want it with braces

A = {1, 2, 3, 4};
Select[(3*# & /@ A), (# < 7 &)]

in other examples this would not work. Then you have the chance to use
Function[{x,y,..},...] and it gets clear to Mathematica.

Cheers
Patrick

Bob Hanlon

unread,
Sep 2, 2009, 3:59:03 AM9/2/09
to

While nesting of pure functions frequently fails due to an ambiguity, your example works fine on my system

$Version

7.0 for Mac OS X x86 (64-bit) (February 19, 2009)

A = {1, 2, 3, 4}

{1,2,3,4}

3 # & /@ A

{3,6,9,12}

Select[%, # < 7 &]

{3,6}

Select[3 # & /@ A, # < 7 &]

{3,6}


Bob Hanlon

---- Erin Noel <eno...@gmail.com> wrote:

=============

Elton Kurt TeKolste

unread,
Sep 2, 2009, 3:59:24 AM9/2/09
to
It seems to me that Select[3*# & /@ A, # < 7 &] works fine. It is
perfectly clear to the reader and to Mathematica which # is scoped with
which &.

In case that this is an example extracted to illustrate a more complex
situation, note that there is always the option of making the function
explicit (& -> Function) and naming the dummy variables.

Select[Function[x,3x]/@A,Function[y,y<7]]

If it helps the clarity of your code, you can even define the functions
separately:

In[23]:= f1 = Function[x, 3 x]

Out[23]= Function[x, 3 x]

In[24]:= f2 = Function[x, x < 7]

Out[24]= Function[x, x < 7]

In[25]:= Select[f1 /@ A, f2]

Out[25]= {3, 6}

Kurt

On Tue, 01 Sep 2009 03:51 -0400, "Erin Noel" <eno...@gmail.com> wrote:
> Hi,
>
> So how would you go about nesting a functional command inside of another
> functional command? For example, say A={1,2,3,4}, then 3*#&/@A =
> {3,6,9,12}.
> No problem. But then what if, within that vector {3,6,9,12}, I wanted to
> use
> the Select command to choose elements less than, say 7. The command
> Select[3*#&/@A,#<7&] doesn't work because, as far as I can tell,
> Mathematica
> doesn't know which "#" belongs to Select and which "#" belongs to the &/@
> mapping over A. I know that I could define 3*#&/@A as a new variable and
> then use that new variable in the Select command, but is there any way to
> nest multiple commands in this way?
>
> Thanks a lot in advance,
> Erin
>
>

Regards,
Kurt Tekolste


Roman

unread,
Sep 2, 2009, 3:59:45 AM9/2/09
to
Erin,
I have solved similar problems with the Function command, which can be
nested without a problem since its arguments are named.
Roman.

Albert Retey

unread,
Sep 2, 2009, 4:00:06 AM9/2/09
to
Hi,

your example is not that good, because it actually works because
Mathematica can distinguish between the # very well, at least for this
case. There are other cases where it can't and there the usual approach
is to not use shortcuts for the pure functions but something like:

Function[{x}, x*# & /@ {1,2,3} ] /@ {1,2,3}

hth,

albert

Leonid Shifrin

unread,
Sep 2, 2009, 4:00:49 AM9/2/09
to
Hi Erin,

first of all, your construction Select[3*#&/@A,#<7&] will work all right.
The ambiguity happens
when you need to use slot variables belonging to pure functions of different
nesting level, at the
same time (in the same expression). A simple way to tell is to look at the
FullForm:

Select[
Map[
Function[Times[3, Slot[1]]], a], Function[Less[Slot[1], 7]]]

This reveals that in your example, there is no nesting at all - pure
functions are completely independent.
However, even when the nesting happens, it is fine as long as variables
referenced in more internal Function-s are not those which belong
(logically) to external ones.

Here is an example of a pure function containing several nested anonimous
functions, but being ok:

Split[Sort[#, First@#1 > First@#2 &], First@#1 == First@#2 &] &

It takes a list, sorts it according to its first element in decreasing
order, and then groups together
sublists with the same first element:

In[1] =
test = RandomInteger[{1, 10}, {10, 2}]

Out[1] =

{{4, 5}, {7, 9}, {10, 7}, {8, 9}, {1, 6}, {2, 3}, {7, 5}, {8, 3}, {1,
1}, {9, 9}}

In[2] =
Split[Sort[#, First@#1 > First@#2 &], First@#1 == First@#2 &] &[test]

Out[2] = {{{10, 7}}, {{9, 9}}, {{8, 3}, {8, 9}}, {{7, 5}, {7, 9}}, {{4,
5}}, {{2, 3}}, {{1, 1}, {1, 6}}}

Using slots everywhere is possible in cases like above, where enitre inner
pure functions are contained in outer ones as one of their arguments, but
not possible in general. Here is an example of a function that takes a list,
and then maps a function {first element,#}& on the rest of the list:

Function[x, {First@x, #} & /@ Rest[x]]

Here, it is not possible to use anonimous functions everywhere, because
there is a place
where both external and internal slot variable will be referenced at once -
in the two-element sublist
being mapped. Here is how it works:

In[3] = Function[x, {First@x, #} & /@ Rest[x]][Range[5]]

Out[3] = {{1, 2}, {1, 3}, {1, 4}, {1, 5}}

An attempt to use slots in both functions here will lead to a run-time error
since
all slots in {First@#,#}& are interpreted as belonging to its (inner) scope:

In[4]:= ({First@#,#}&/@Rest[#])&[Range[5]]

During evaluation of In[4]:= First::normal: Nonatomic expression expected at
position 1 in First[2]. >>
During evaluation of In[4]:= First::normal: Nonatomic expression expected at
position 1 in First[3]. >>
During evaluation of In[4]:= First::normal: Nonatomic expression expected at
position 1 in First[4]. >>
During evaluation of In[4]:= General::stop: Further output of First::normal
will be suppressed during this calculation. >>

Out[4]= {{First[2],2},{First[3],3},{First[4],4},{First[5],5}}

You may want to check out a chapter on pure functions in my book:

http://www.mathprogramming-intro.org/book/node50.html

where I also discuss this and related topics.

Hope this helps.

Regards,
Leonid


On Tue, Sep 1, 2009 at 11:51 AM, Erin Noel <eno...@gmail.com> wrote:

> Hi,
>
> So how would you go about nesting a functional command inside of another
> functional command? For example, say A={1,2,3,4}, then 3*#&/@A =
> {3,6,9,12}.
> No problem. But then what if, within that vector {3,6,9,12}, I wanted to
> use
> the Select command to choose elements less than, say 7. The command
> Select[3*#&/@A,#<7&] doesn't work because, as far as I can tell,
> Mathematica
> doesn't know which "#" belongs to Select and which "#" belongs to the &/@
> mapping over A. I know that I could define 3*#&/@A as a new variable and
> then use that new variable in the Select command, but is there any way to
> nest multiple commands in this way?
>

Bill Rowe

unread,
Sep 2, 2009, 4:05:16 AM9/2/09
to
On 9/1/09 at 3:51 AM, eno...@gmail.com (Erin Noel) wrote:

>So how would you go about nesting a functional command inside of
>another functional command? For example, say A={1,2,3,4}, then
>3*#&/@A = {3,6,9,12}. No problem. But then what if, within that
>vector {3,6,9,12}, I wanted to use the Select command to choose
>elements less than, say 7. The command Select[3*#&/@A,#<7&] doesn't
>work because, as far as I can tell, Mathematica doesn't know which
>"#" belongs to Select and which "#" belongs to the &/@ mapping over
>A. I know that I could define 3*#&/@A as a new variable and then use
>that new variable in the Select command, but is there any way to
>nest multiple commands in this way?

You can do what you are trying to do with either

In[28]:= Select[(3 # & /@ a), # > 7 &]

Out[28]= {9,12}

or

In[27]:= Select[Map[3 # &, a], # > 7 &]

Out[27]= {9,12}

However, both of these are doing more work than is needed in
this case. Times as the attribute Listable. So,

In[29]:= Select[3 a, # > 7 &]

Out[29]= {9,12}

which is also more readable code.

Note, I've used a lower case a as the variable rather than an
uppercase A since it is generally not a good idea to use
uppercase letters as variables. Using lower case letters is
guaranteed to avoid conflicts with built in symbols and functions.


pfalloon

unread,
Sep 2, 2009, 4:05:47 AM9/2/09
to
On Sep 1, 5:51 pm, Erin Noel <eno...@gmail.com> wrote:
> Hi,
>
> So how would you go about nesting a functional command inside of another
> functional command? For example, say A={1,2,3,4}, then 3*#&/@A = {3,6=

,9,12}.
> No problem. But then what if, within that vector {3,6,9,12}, I wanted to use
> the Select command to choose elements less than, say 7. The command
> Select[3*#&/@A,#<7&] doesn't work because, as far as I can tell, Mathematica
> doesn't know which "#" belongs to Select and which "#" belongs to the &/@
> mapping over A. I know that I could define 3*#&/@A as a new variable and
> then use that new variable in the Select command, but is there any way to
> nest multiple commands in this way?
>
> Thanks a lot in advance,
> Erin

As it happens, the example you give works exactly as you would want it
to:

In[215]:= A = Range[4];
Select[3*#& /@ A, #<7&]
Out[216]= {3,6}

For most such cases, Mathematica is able to understand which function
each # belongs to. In the case above, the two arguments to Select are
evaluated one after the other, so there is no chance of confusing the
sense of each #.

More generally, my experience is that Mathematica can parse
complicated nested anonymous functions better than humans (or at
least, better than me), so good programming style dictates that it is
rarely necessary to nest things in a way that risks confusion (and
IMO, where confusion is even remotely possible, it's much better to
define intermediate variables so that your code makes sense).

Cheers,
Peter.

DrMajorBob

unread,
Sep 3, 2009, 5:31:57 AM9/3/09
to
Better yet,

a = {1, 2, 3, 4};
Select[3 a, (# < 7 &)]

{3, 6}

As for how to "nest functional commands", my answer is simple: don't. It's
never necessary, and it makes for less readable code.

Bobby

On Wed, 02 Sep 2009 02:59:25 -0500, Patrick Scheibe
<psch...@trm.uni-leipzig.de> wrote:

> Hi,
>
> in this case it is easy. Just "say" how you want it with braces
>
> A = {1, 2, 3, 4};
> Select[(3*# & /@ A), (# < 7 &)]
>
> in other examples this would not work. Then you have the chance to use
> Function[{x,y,..},...] and it gets clear to Mathematica.
>
> Cheers
> Patrick
>
>

> On Tue, 2009-09-01 at 03:51 -0400, Erin Noel wrote:
>> Hi,
>>
>> So how would you go about nesting a functional command inside of another
>> functional command? For example, say A={1,2,3,4}, then 3*#&/@A =

>> {3,6,9,12}.


>> No problem. But then what if, within that vector {3,6,9,12}, I wanted
>> to use
>> the Select command to choose elements less than, say 7. The command
>> Select[3*#&/@A,#<7&] doesn't work because, as far as I can tell,
>> Mathematica
>> doesn't know which "#" belongs to Select and which "#" belongs to the
>> &/@
>> mapping over A. I know that I could define 3*#&/@A as a new variable and
>> then use that new variable in the Select command, but is there any way
>> to
>> nest multiple commands in this way?
>>
>> Thanks a lot in advance,
>> Erin
>>
>>
>
>

--
DrMaj...@yahoo.com

0 new messages