APL question

This is a discussion on APL question within the APL forums in Programming Languages category; Hello, I'm working on a parametric (hermite, bezier, b-spline, etc) curve/surface/volume library as my first real piece of APL. I have a question about how to do a certain operation without loops. I need to construct a binomial coefficient and have written a function like this: n binc i (x/{iota}n) {divide} (x/{iota}i) x x/{iota}n-i This works for things like 5 binc 2, which is 10. My question is: if i is a vector, so I might call the function like this: 5 binc 0 1 2 3 4 5 How can I get the response of a vector like 1 ...

Go Back   Application Development Forum > Programming Languages > APL

Object Mix

Register FAQ Calendar Search Today's Posts Mark Forums Read
  #1  
Old 10-16-2008, 11:56 PM
Peter Keller
Guest
 
Default APL question

Hello,

I'm working on a parametric (hermite, bezier, b-spline, etc)
curve/surface/volume library as my first real piece of APL.

I have a question about how to do a certain operation without loops.

I need to construct a binomial coefficient and have written a function like
this:

n binc i
(x/{iota}n) {divide} (x/{iota}i) x x/{iota}n-i

This works for things like 5 binc 2, which is 10.

My question is: if i is a vector, so I might call the function like this:

5 binc 0 1 2 3 4 5

How can I get the response of a vector like
1 5 10 10 5 1
from binc?

Do I need an explicit loop to iterate the operation across vector i
{rho}i times?

In scheme (for those who might know it), I could encapsulate binc into
a higher order function, currying one of the arguments, and then map it
across the vector i, like this:

(map (lambda (x) (binc 5 x)) '(0 1 2 3 4 5))

But I don't know how to do a similar thing in APL without the explicit loops.

Thank you.

-pete
Reply With Quote
  #2  
Old 10-17-2008, 12:29 AM
Paul Houle
Guest
 
Default Re: APL question


5 binc {each} 0 1 2 3 4 5

....Paul

"Peter Keller" <psilord@merlin.cs.wisc.edu> wrote in message
news:48f80d02$0$9898$80265adb@spool.cs.wisc.edu...
> Hello,
>
> I'm working on a parametric (hermite, bezier, b-spline, etc)
> curve/surface/volume library as my first real piece of APL.
>
> I have a question about how to do a certain operation without loops.
>
> I need to construct a binomial coefficient and have written a function
> like
> this:
>
> n binc i
> (x/{iota}n) {divide} (x/{iota}i) x x/{iota}n-i
>
> This works for things like 5 binc 2, which is 10.
>
> My question is: if i is a vector, so I might call the function like this:
>
> 5 binc 0 1 2 3 4 5
>
> How can I get the response of a vector like
> 1 5 10 10 5 1
> from binc?
>
> Do I need an explicit loop to iterate the operation across vector i
> {rho}i times?
>
> In scheme (for those who might know it), I could encapsulate binc into
> a higher order function, currying one of the arguments, and then map it
> across the vector i, like this:
>
> (map (lambda (x) (binc 5 x)) '(0 1 2 3 4 5))
>
> But I don't know how to do a similar thing in APL without the explicit
> loops.
>
> Thank you.
>
> -pete



Reply With Quote
  #3  
Old 10-17-2008, 12:35 AM
Paul Houle
Guest
 
Default Re: APL question

Though you really want to re-write your function:

r {gets} n binc i
r {gets} (x/{iota}n) {divide} (x/{iota}i) x x/{iota}n-i

So you can use the result in subsequent calculation.
....Paul

"Paul Houle" <asmguru@yahoo.com> wrote in message
news:qwUJk.2652$hc1.2401@flpi150.ffdc.sbc.com...
>
> 5 binc {each} 0 1 2 3 4 5
>
> ...Paul
>
> "Peter Keller" <psilord@merlin.cs.wisc.edu> wrote in message
> news:48f80d02$0$9898$80265adb@spool.cs.wisc.edu...
>> Hello,
>>
>> I'm working on a parametric (hermite, bezier, b-spline, etc)
>> curve/surface/volume library as my first real piece of APL.
>>
>> I have a question about how to do a certain operation without loops.
>>
>> I need to construct a binomial coefficient and have written a function
>> like
>> this:
>>
>> n binc i
>> (x/{iota}n) {divide} (x/{iota}i) x x/{iota}n-i
>>
>> This works for things like 5 binc 2, which is 10.
>>
>> My question is: if i is a vector, so I might call the function like this:
>>
>> 5 binc 0 1 2 3 4 5
>>
>> How can I get the response of a vector like
>> 1 5 10 10 5 1
>> from binc?
>>
>> Do I need an explicit loop to iterate the operation across vector i
>> {rho}i times?
>>
>> In scheme (for those who might know it), I could encapsulate binc into
>> a higher order function, currying one of the arguments, and then map it
>> across the vector i, like this:
>>
>> (map (lambda (x) (binc 5 x)) '(0 1 2 3 4 5))
>>
>> But I don't know how to do a similar thing in APL without the explicit
>> loops.
>>
>> Thank you.
>>
>> -pete

>
>



Reply With Quote
  #4  
Old 10-17-2008, 12:55 AM
Peter Keller
Guest
 
Default Re: APL question

Paul Houle <asmguru@yahoo.com> wrote:
> Though you really want to re-write your function:
>
> r {gets} n binc i
> r {gets} (x/{iota}n) {divide} (x/{iota}i) x x/{iota}n-i
>
> So you can use the result in subsequent calculation.
> ...Paul
>
> "Paul Houle" <asmguru@yahoo.com> wrote in message
> news:qwUJk.2652$hc1.2401@flpi150.ffdc.sbc.com...
>>
>> 5 binc {each} 0 1 2 3 4 5


Wow. I somehow had typed every other combination of {each} except the
one you just did, which I tried and it worked just fine. That is pretty
cool and makes me very happy since currying in this manner is a common
idiom I wish to use.

And I rewrote my functions about 5 minutes before you mentioned why as I
had just puzzled out the VALUE ERROR I was getting in APLX.

However, I have another function, berp, which is the berstein polynomial
that takes the binomial coefficient parameters, plus a parameteric variable
which represents a location on the bernstein polynomial curve.

It looks like this:

Z {gets} c berp u
Z {gets} (c[2] binc c[1]) x (u*c[1]) x (1-u)*c[2]-c[1]

And produces good answers:

> 1 2 berp 0

0

> 1 2 berp .5

..5

> 1 2 berp 1

0

However, when I try the same trick:

1 2 berp {each} 0 .1 .2 .3 .4 .5 .6 .7 .8 .9 1

It fails with a LENGTH ERROR on the marker on 1.

Why doesn't {each} work in this context? Do I not have a vector on the left
in the same manner that 5 binc {each} 0 1 2 3 4 5 did?

Thank you.

-pete
Reply With Quote
  #5  
Old 10-17-2008, 01:38 AM
Paul Houle
Guest
 
Default Re: APL question

You need to enclose the left argument (scalarizing it) to distribute it
properly across all the right arguments.

({enclose}1 2) berp {each} 0 .1 .2 .3 .4 .5 .6 .7 .8 .9 1

....Paul

"Peter Keller" <psilord@merlin.cs.wisc.edu> wrote in message
news:48f81aab$0$9898$80265adb@spool.cs.wisc.edu...
> Paul Houle <asmguru@yahoo.com> wrote:
>> Though you really want to re-write your function:
>>
>> r {gets} n binc i
>> r {gets} (x/{iota}n) {divide} (x/{iota}i) x x/{iota}n-i
>>
>> So you can use the result in subsequent calculation.
>> ...Paul
>>
>> "Paul Houle" <asmguru@yahoo.com> wrote in message
>> news:qwUJk.2652$hc1.2401@flpi150.ffdc.sbc.com...
>>>
>>> 5 binc {each} 0 1 2 3 4 5

>
> Wow. I somehow had typed every other combination of {each} except the
> one you just did, which I tried and it worked just fine. That is pretty
> cool and makes me very happy since currying in this manner is a common
> idiom I wish to use.
>
> And I rewrote my functions about 5 minutes before you mentioned why as I
> had just puzzled out the VALUE ERROR I was getting in APLX.
>
> However, I have another function, berp, which is the berstein polynomial
> that takes the binomial coefficient parameters, plus a parameteric
> variable
> which represents a location on the bernstein polynomial curve.
>
> It looks like this:
>
> Z {gets} c berp u
> Z {gets} (c[2] binc c[1]) x (u*c[1]) x (1-u)*c[2]-c[1]
>
> And produces good answers:
>
>> 1 2 berp 0

> 0
>
>> 1 2 berp .5

> .5
>
>> 1 2 berp 1

> 0
>
> However, when I try the same trick:
>
> 1 2 berp {each} 0 .1 .2 .3 .4 .5 .6 .7 .8 .9 1
>
> It fails with a LENGTH ERROR on the marker on 1.
>
> Why doesn't {each} work in this context? Do I not have a vector on the
> left
> in the same manner that 5 binc {each} 0 1 2 3 4 5 did?
>
> Thank you.
>
> -pete



Reply With Quote
  #6  
Old 10-17-2008, 01:57 AM
Peter Keller
Guest
 
Default Re: APL question

Paul Houle <asmguru@yahoo.com> wrote:
> You need to enclose the left argument (scalarizing it) to distribute it
> properly across all the right arguments.
>
> ({enclose}1 2) berp {each} 0 .1 .2 .3 .4 .5 .6 .7 .8 .9 1


Hrm.... So once inside the berp function, how does berp know that the left
hand side is a vector of length 2 where index 1 is 1 and index 2 is 2, instead
of thinking that the left hand side is a single vector which contains
one element which is another vector containing 1 and 2?

I'm definitely confused on the semantic reasoning for why {enclose} behaves
correctly in this case.

I'm unsure what the difference are between these and why the
implementation of berp knows what the left hand side looks like in the
1st and 4th example:

1 2 berp .5
({enclose}1 2) berp .5
1 2 berp {each} 0 .1 .2 .3 .4 .5 .6 .7 .8 .9 1
({enclose}1 2) berp {each} 0 .1 .2 .3 .4 .5 .6 .7 .8 .9 1

Thank you.

-pete
Reply With Quote
  #7  
Old 10-17-2008, 02:07 AM
James J. Weinkam
Guest
 
Default Re: APL question

Peter Keller wrote:
> Hello,
>
> I'm working on a parametric (hermite, bezier, b-spline, etc)
> curve/surface/volume library as my first real piece of APL.
>
> I have a question about how to do a certain operation without loops.
>
> I need to construct a binomial coefficient and have written a function like
> this:
>
> n binc i
> (x/{iota}n) {divide} (x/{iota}i) x x/{iota}n-i
>
> This works for things like 5 binc 2, which is 10.
>
> My question is: if i is a vector, so I might call the function like this:
>
> 5 binc 0 1 2 3 4 5
>
> How can I get the response of a vector like
> 1 5 10 10 5 1
> from binc?
>
> Do I need an explicit loop to iterate the operation across vector i
> {rho}i times?


Why are you writing your own function? Dyadic ! (binomial coefficient)
is a primitive scalar function which does everything you want.

2!5
10
{quad}IO{is}0
({iota}6)!5
1 5 10 10 5 1
Reply With Quote
  #8  
Old 10-17-2008, 02:24 AM
Paul Houle
Guest
 
Default Re: APL question


The berp function never "sees" the effects of the {each}.
The {each} operator simply executes berp multiple times with the appropriate
arguments and combines the results.

{each} implicitly does a disclose of the left and right arguments, before
each call to berp, pairing scalars beforehand in the normal scalar dyadic
manner.

Similar to how 1+3 4 5 executes as 1 1 1+3 4 5, ({enclose}1 2)
berp{each} 0 .1 .2 executes as ((1 2)(1 2)(1 2)) berp{each} 0 .1 .2

It might be a good idea to play around with {enclose} and {each} on a
primitive function to get a feel for how they work.
For instance replace "berp" with "+" in the examples you're working with.

....Paul

"Peter Keller" <psilord@merlin.cs.wisc.edu> wrote in message
news:48f82939$0$9896$80265adb@spool.cs.wisc.edu...
> Paul Houle <asmguru@yahoo.com> wrote:
>> You need to enclose the left argument (scalarizing it) to distribute it
>> properly across all the right arguments.
>>
>> ({enclose}1 2) berp {each} 0 .1 .2 .3 .4 .5 .6 .7 .8 .9 1

>
> Hrm.... So once inside the berp function, how does berp know that the left
> hand side is a vector of length 2 where index 1 is 1 and index 2 is 2,
> instead
> of thinking that the left hand side is a single vector which contains
> one element which is another vector containing 1 and 2?
>
> I'm definitely confused on the semantic reasoning for why {enclose}
> behaves
> correctly in this case.
>
> I'm unsure what the difference are between these and why the
> implementation of berp knows what the left hand side looks like in the
> 1st and 4th example:
>
> 1 2 berp .5
> ({enclose}1 2) berp .5
> 1 2 berp {each} 0 .1 .2 .3 .4 .5 .6 .7 .8 .9 1
> ({enclose}1 2) berp {each} 0 .1 .2 .3 .4 .5 .6 .7 .8 .9 1
>
> Thank you.
>
> -pete



Reply With Quote
  #9  
Old 10-17-2008, 08:10 AM
Stephen Taylor
Guest
 
Default Re: APL question

On Oct 17, 7:57*am, Peter Keller <psil...@merlin.cs.wisc.edu> wrote:
> Paul Houle <asmg...@yahoo.com> wrote:
> > You need to enclose the left argument (scalarizing it) to distribute it
> > properly across all the right arguments.

>
> > * * ({enclose}1 2) berp {each} 0 .1 .2 .3 .4 .5 .6 .7 .8 .9 1

>
> Hrm.... So once inside the berp function, how does berp know that the left
> hand side is a vector of length 2 where index 1 is 1 and index 2 is 2, instead
> of thinking that the left hand side is a single vector which contains
> one element which is another vector containing 1 and 2?
>
> I'm definitely confused on the semantic reasoning for why {enclose} behaves
> correctly in this case.
>
> I'm unsure what the difference are between these and why the
> implementation of berp knows what the left hand side looks like in the
> 1st and 4th example:
>
> * * *1 2 berp .5
> * * *({enclose}1 2) berp .5
> * * *1 2 berp {each} 0 .1 .2 .3 .4 .5 .6 .7 .8 .9 1
> * * *({enclose}1 2) berp {each} 0 .1 .2 .3 .4 .5 .6 .7 .8 .9 1
>
> Thank you.
>
> -pete


An alternative to enclosing the left argument is to use the compose
operator to curry it to a monadic function:

1 2{compose}berp {each} 0 .1 .2 .3 .4 .5 .6 .7 .8 .9 1

Sounds like that fits your thought more closely.

Stephen
editor@vector.org.uk
Reply With Quote
  #10  
Old 10-17-2008, 11:07 AM
Peter Keller
Guest
 
Default Re: APL question

James J. Weinkam <jjw@cs.sfu.ca> wrote:
> Why are you writing your own function? Dyadic ! (binomial coefficient)
> is a primitive scalar function which does everything you want.
>
> 2!5
> 10
> {quad}IO{is}0
> ({iota}6)!5
> 1 5 10 10 5 1


*sheepish grin* I hadn't realized that function was available....

I realize that I will not be writing good APL initially and have to unlearn
habits from other languages to really understand APL. So, sometimes I may
make missteps, like not realizing there was already something which would
do exactly what I needed.

Thank you.

-pete
Reply With Quote
Reply


Thread Tools
Display Modes


All times are GMT -5. The time now is 10:29 PM.


Powered by vBulletin® Version 3.7.2
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
vB Ad Management by =RedTyger=

In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.