Partial function application (was: Re: Binding precedence for first sym...)

Trans wrote:

Musing on this, you know what'd be really great? Support for >

partial function application! I suppose this could already be

emulated (or, more aptly, evamulated), but it could be a really >

useful feature. Those pesky side-effects just get in the way

but I'm sure that could be overcome :slight_smile:

Forgive me but I have no idea what you are talking about. If you are
being serious, what is partial function application? What would the
advantages be? Would the advantage offset the disadvatages it may
create elsewhere? If you were not, then please don't afford yourself as
so funny.

Oh, I was serious. Partial function application (also referred to as
'macro binding' and 'currying') means that given a certain function
(or method), e.g.

def fun(x, y, z)
聽聽q = x + y + z
end

If this function is invoked with a partial argument list, e.g.

fun 1, 2

Then, instead of throwing some sort of an error, the call would
produce a new function where the given arguments are bound.
Essentially, the previous call would yield:

def fun(z)
聽聽q = 1 + 2 + z
end

So these calls would be equal:

fun(1, 2, 3) # => 6
((fun 1, 2) 3) # => 6
fun(1, 2)(3) # => 6
x = fun(1, 2); x(3) # => 6
聽聽聽聽聽聽聽聽
The only problem would be handling the destructive updates, i.e. what
would happen if one tried to curry this with x:

def fun(x, y, z)
聽聽x = x + y + z
end

x can't be directly substituted since it's assigned to. It'd have to
be translated to 'xx = x + y + z' or something.

This probably isn't something most Rubyists, at least initially, would
be excited about but it's quite useful. I think it'd be possible to
implement as a library but it'd obviously be fairly slow. Of course
there's always Haskell :slight_smile:

I believe it was Richard Feynman who said, though I paraphrase, "Never
underestimate the power of a new notation."

T

E

E S wrote:

Oh, I was serious. Partial function application (also referred to as
'macro binding' and 'currying') means that given a certain function
(or method), e.g.

Ah, forgive me! I have heared of curry. I like to eat it :slight_smile: I have
never noticed these other names for it before.

def fun(x, y, z)
聽聽q = x + y + z
end

If this function is invoked with a partial argument list, e.g.

fun 1, 2

Then, instead of throwing some sort of an error, the call would
produce a new function where the given arguments are bound.
Essentially, the previous call would yield:

def fun(z)
聽聽q = 1 + 2 + z
end

So these calls would be equal:

fun(1, 2, 3) # => 6
((fun 1, 2) 3) # => 6
fun(1, 2)(3) # => 6
x = fun(1, 2); x(3) # => 6

I highly regard this. It should be so.

The only problem would be handling the destructive updates, i.e. what

would happen if one tried to curry this with x:

def fun(x, y, z)
聽聽x = x + y + z
end

x can't be directly substituted since it's assigned to. It'd have to
be translated to 'xx = x + y + z' or something.

I do not see a problem. The x is local and has no functional baring.
The translation is simply:

fun(1,2) #=>

def fun(1, 2, z)
x = 1 + 2 + z
end

This probably isn't something most Rubyists, at least initially,

would

be excited about but it's quite useful. I think it'd be possible to
implement as a library but it'd obviously be fairly slow. Of course
there's always Haskell :slight_smile:

I am for it. Much more so then for my silly symbol notation :wink:

T

E S wrote:

Oh, I was serious. Partial function application (also referred to as
'macro binding' and 'currying') means that given a certain function (or method), e.g.

def fun(x, y, z)
聽聽q = x + y + z
end

If this function is invoked with a partial argument list, e.g.

fun 1, 2

Then, instead of throwing some sort of an error, the call would produce a new function where the given arguments are bound. Essentially, the previous call would yield:

def fun(z)
聽聽q = 1 + 2 + z
end

So these calls would be equal:

fun(1, 2, 3) # => 6
((fun 1, 2) 3) # => 6
fun(1, 2)(3) # => 6
x = fun(1, 2); x(3) # => 6
聽聽聽聽聽聽聽聽The only problem would be handling the destructive updates, i.e. what would happen if one tried to curry this with x:

def fun(x, y, z)
聽聽x = x + y + z
end

x can't be directly substituted since it's assigned to. It'd have to be translated to 'xx = x + y + z' or something.

This probably isn't something most Rubyists, at least initially, would
be excited about but it's quite useful. I think it'd be possible to implement as a library but it'd obviously be fairly slow. Of course there's always Haskell :slight_smile:

This isn't exactly what you were asking for, but it fills some of the gap. It's a fairly straightforward (i.e., ripped off from) translation of an example by Paul Graham in _ANSI_Common_Lisp_ (pg. 110). He was attempting to simulate a similar feature from Dylan.

def curry(f, *args)
聽聽聽lambda {|*args2| f.call(*(args + args2))}
end

fun = lambda {|x, y, z| x + y + z}
fun.call(1, 2, 3) => 6

f1 = curry(fun, 1)
f1.call(2, 3) => 6

f2 = curry(fun, 1, 2)
f2.call(3) => 6

I'm fairly new to Ruby, but I think this is the right way to do this.

David Sletten

> def fun(x, y, z)
> x = x + y + z
> end
>
> x can't be directly substituted since it's assigned to. It'd have to
> be translated to 'xx = x + y + z' or something.

I do not see a problem. The x is local and has no functional baring.
The translation is simply:

fun(1,2) #=>

def fun(1, 2, z)
x = 1 + 2 + z
end

How about this:

def fun(z)
聽聽聽x = 1
聽聽聽y = 2

聽聽聽# unmodified original
聽聽聽x = x + y + z
end

Then you shouldn't need to worry about rewriting as they would act
more like defult params.

Douglas

One thing to make noteworthy are the subtleties bugwise that changing
proc can have on a program (that bit me in the rear a couple of
times)... I think there should definitely be warnings in any file that
does stuff with Proc about such things (as it is entirely subtle, in
my opinion)...

example:

class Proc
聽聽def data(arg)
聽聽聽聽@arg
聽聽end
聽聽def data=(arg)
聽聽聽聽@arg = arg
聽聽end
end

anon = Proc.new {
聽聽p @data
}

def foo
聽聽yield
end

anon[] # prints nil
anon.data = 1
anon[] # prints 1
foo(&anon) # prints nil

-- thus, internal data is not kept as the structure is transformed
from proc to block...

~Me!

路路路

--
There's no word in the English language for what you do to a dead
thing to make it stop chasing you.

Douglas Livingstone wrote:

How about this:

def fun(z)
聽聽聽x = 1
聽聽聽y = 2

聽聽聽# unmodified original
聽聽聽x = x + y + z
end

Then you shouldn't need to worry about rewriting as they would act
more like defult params.

Nice.

This isn't even what he was asking for, though. The OP wanted a
`saved arguments' thing like currying... hardcoding in x and y is the
same as hardcoding 1 and 2 in the q (or x in OP's one example) = x +
y+ z...

Also, I've made a few small updates to my curry file, if anyone is
interested (just default behaviors for certain methods invoked without
any information to use).

Given that the OP mentioned Haskell, I think we should all try to come
up with some language that has the wonderfulness of Haskell with the
wonderful ness of Ruby. We could call it Rascal. Since Haskell cats
are all about domain specific languages, we could call DSLs in Rascal
"Little Rascals"... :slight_smile:

~Me!

路路路

On Wed, 2 Feb 2005 02:50:44 +0900, Trans <transfire@gmail.com> wrote:

Douglas Livingstone wrote:
> How about this:
>
> def fun(z)
> x = 1
> y = 2
>
> # unmodified original
> x = x + y + z
> end
>
> Then you shouldn't need to worry about rewriting as they would act
> more like defult params.

Nice.

--
There's no word in the English language for what you do to a dead
thing to make it stop chasing you.

This isn't even what he was asking for, though. The OP wanted a
`saved arguments' thing like currying... hardcoding in x and y is the
same as hardcoding 1 and 2 in the q (or x in OP's one example) = x +
y+ z...

I thought that Trans was posting a target for the generated code after
the call to the function is made with too-few arguments. So if
fun(1,2) was called, it would generate and return an object
representing the function I posted above. But the two important steps,
capturing the function call and retruning a "function object", I don't
know how to do :frowning:

I do remember seeing sometihng like def fun:pre() in a slide talking
about Ruby 2 though...

Douglas

Indeed. Count me in as a user of this when you come up with it.

cjs

路路路

On Wed, 2 Feb 2005, Matt Maycock wrote:

Given that the OP mentioned Haskell, I think we should all try to come
up with some language that has the wonderfulness of Haskell with the
wonderful ness of Ruby.

--
Curt Sampson <cjs@cynic.net> +81 90 7737 2974 http://www.NetBSD.org
聽聽聽聽聽聽Make up enjoying your city life...produced by BIC CAMERA

Then again it wouldn't be much different from doing:

class << self
define_method( :"fun(1,2)" do |z|
fun(1,2,z)
end
method :"fun(1,2)"
end

Something like that. And I suspect one should actually alias the
original method first.

T

I'm also interested in this since they are my main languages (real
order is Ruby, C and Haskell though). They are so very different
though, so I'm not sure what it a mix "would mean". Pattern matching
added to Ruby? Type inference added to Ruby? (would only be a
performance issue? If so would it really change the language?) Dynamic
typing added to Haskell? (Sort of meaningless statement!? ;)) etc...
Maybe a wiki for this somewhere?

Best,

Robert Feldt

路路路

On Tue, 8 Feb 2005 12:11:42 +0900, Curt Sampson <cjs@cynic.net> wrote:

On Wed, 2 Feb 2005, Matt Maycock wrote:

> Given that the OP mentioned Haskell, I think we should all try to come
> up with some language that has the wonderfulness of Haskell with the
> wonderful ness of Ruby.

Indeed. Count me in as a user of this when you come up with it.

I think merd was intended to be a Ruby/Haskell middle ground. Not
showing too many signs of activity last I checked, though.

martin

路路路

Robert Feldt <robert.feldt@gmail.com> wrote:

>
I'm also interested in this since they are my main languages (real
order is Ruby, C and Haskell though). They are so very different
though, so I'm not sure what it a mix "would mean". Pattern matching
added to Ruby? Type inference added to Ruby? (would only be a
performance issue? If so would it really change the language?) Dynamic
typing added to Haskell? (Sort of meaningless statement!? ;)) etc...
Maybe a wiki for this somewhere?

Hi Bob,

have you read "Constructive Deconstruction of Subtyping" by
AlistairCockburn ?

http://alistair.cockburn.us/crystal/articles/cdos/constructivedesconstructionofsubtyping.htm

(PS: yes, there's a typo in the url, it's normal)

I haven't read it all, but my impression is that it's very relevant (and
even key) in understanding the gap (or should i say: tension?) between
type-inference on one side and reflection/mutabilities/duck-typing on the
other side.

路路路

On Tue, 8 Feb 2005, Robert Feldt wrote:

On Tue, 8 Feb 2005 12:11:42 +0900, Curt Sampson <cjs@cynic.net> wrote:
> On Wed, 2 Feb 2005, Matt Maycock wrote:
> > Given that the OP mentioned Haskell, I think we should all try to come
> > up with some language that has the wonderfulness of Haskell with the
> > wonderful ness of Ruby.
> Indeed. Count me in as a user of this when you come up with it.
I'm also interested in this since they are my main languages (real
order is Ruby, C and Haskell though). They are so very different
though, so I'm not sure what it a mix "would mean". Pattern matching
added to Ruby? Type inference added to Ruby? (would only be a
performance issue? If so would it really change the language?) Dynamic
typing added to Haskell? (Sort of meaningless statement!? ;)) etc...
Maybe a wiki for this somewhere?

_____________________________________________________________________
Mathieu Bouchard -=- Montr茅al QC Canada -=- http://artengine.ca/matju