Functional programming

Hi –

On Mon, 12 Jan 2009, Mike G. wrote:

You can always write wrappers which convert a given method or lambda
to a one-argument lambda expecting an array. But this is just another
kind of Lisp emulation in Ruby, taking non-homogeneous primitives and
making them homogeneous.

Can you give an example of the kind of meaning-changing you mean –
that is, what you would be doing if you could do it? I’m not quite
getting it.

David


David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Coming in 2009: The Well-Grounded Rubyist (The Well-Grounded Rubyist)

http://www.wishsight.com => Independent, social wishlist management!

Mike G. [email protected] writes:

Do you propose to change every method in the ruby standard library
to take just one argument–an array? That would work. Sounds like
Lisp.

Lisp is not like that.

Pascal J. Bourguignon wrote:

Mike G. [email protected] writes:

Do you propose to change every method in the ruby standard library
to take just one argument–an array? That would work. Sounds like
Lisp.

Lisp is not like that.

I had hoped it was a given that nothing can be done to actually make
Ruby like Lisp.

In the same spirit of how you fiddled around with Ruby until mapcar sort
of worked, another route is to remove the notion of the function
argument list, replacing it with an array, so that the examples I gave
worked. In both cases we are artificially removing syntactical
differences, and in this sense it is closer to Lisp.

“William J.” [email protected] writes:

end)
(x . car)
irb(main):040:0> (cons 1,2)
true
(break)
@cdr=#<Cons:0x7fdfb53b8228 @cdr=nil, @car=3>, @car=2>, @car=1>
end)
end)
end)

(def endp(list)

(3 2 1)

message:

  (arity = (arity - 1))

(def function(designator,arity=(-1))
join(" , "))) (sep = " ")
elsif (arity == 0)

irb(main):478:0> (begin
as it should be when you use Commune Lisp!

(cons (funcall fun,(first list)),(mapcar fun,(rest list)))
nil

result along with the parameters. We process the list item by item
end)
(printlist (mapcar (function :smallest,1),(list (list 1),

Ruby:

No, you’re wrong. All the above code IS RUBY!

[[1],[1,1,1,1],[1,2,3,4],[4,3,2,1],[1,2,3,4,3,2,1],[4,3,2,1,2,3,4]].
map{|a| a.min}
==>[1, 1, 1, 1, 1, 1]

Yes, COBOL Lisp is an ancient, cumbersome, and clunky language.
Ruby is to it as a transistor is to a vacuum tube.

Wrong, the above code wasn’t Lisp, it was Matzacred Lisp, aka Ruby.

Ruby is to a vacuum tube what debris of glass and tungsten filaments
are.

Mike G. wrote:

Brian C. wrote:

(2) to understand Mike’s assertion
that Ruby lambdas are not first-class functions (i.e. “The difference
between lambda { } and a real first-class function is quite profound”).

Ruby:

mean = lambda { |*args|
(args.inject(0) { |acc, x| acc + x })/args.size.to_f
}
data = [[1,2,3], [4,5,6,7]]

data.map(&mean) # fail
data.map(&:mean) # fail
data.map { |*numbers| mean.call(*numbers) } # fail
data.map { |numbers| mean.call(*numbers) } # phew, found it

OK, I think I see what you’re getting at. You’ve written a lambda with a
splat (i.e. which takes a variable number of arguments), but needed a
splat at the caller side too. Otherwise the lambda receives a single
argument, which is an Array object.

You could have written the lambda to take a single Array argument:

mean = lambda { |arg| arg.inject(0) …etc }

I don’t know enough about Lisp to say how Lisp resolves the same
dichotomy, but surely it must exist. That is, there must be a difference
between calling a function foo with a (list of) n arguments, and calling
a function foo with 1 argument which is itself a list?

Mike G. wrote:

Can you give an example of where the difference is “very useful”?

Well, as you know, blocks are roughly just in-line lambdas:

10.times { |x| puts x }

I was thinking of the following properties of the method/lambda
difference:

(1) You can return directly from a method, even from inside blocks.

class Foo
def bar
10.times { |x| …
10.times { |y| …
return “foo” if baz(x,y)
}
}
end
end

(2) The whole variable/method naming thing only works because a method
starts a new scope, but a block doesn’t.

That is: when I write an expression like ‘a+1’ I don’t have to mark
whether ‘a’ is a call to a method, or retrieving the value from a local
variable. Neither do I need to declare a to be a variable or a method. I
just use it, and a simple rule says whether what it is, from the
context.

Finally: I just happen to like infix expressions, maybe because these
are how we think in real life, and what we’re all taught in school from
an early age. In these, a+1 and (a+1) and ((a+1)) are the same
expression.

In Lisp, it makes a huge semantic difference whether I write
parentheses, and how many, because the Lisp brackets are also in effect
the apply-function operator: like a() in C. So I have to constantly
think about whether I should write ‘a’ or ‘(a)’ or ‘(quote a)’ or
whatever.

Again, this is saying more about my mind, and possibly my upbringing,
than anything else. My mind is not a Lisp processor.

Because programmers can and should always be refactoring and changing
their mind, this entails the drudgework of adding/removing the
'.call()'s or the '[]'s or (in ruby 1.9) the '.()'s. The worst
outcome is when a programmer doesn’t bother to refactor because of the
hassle.

It’s not a problem I’ve ever come across in practice. For me,
refactoring usually means moving code between methods in a class, or
between methods in one class and another class. Usually, code which
expects a block always expects a block.

By the way, since locals are determined at parse time, I don’t see any
particular reason why this cannot work:

bisect = lambda { |x, y| (x + y)/2.0 }

bisect(5, 6)

Whether or not that should work is a different story. The pro is
that I can swap lambdas and methods without changing syntax. The con
is, at least, that the meaning of existing code could change (when a
bisect method already exists).

Sure. In practice, Ruby programs aren’t usually composed like that,
since local variables are considered “short lived” (they only exist
during executing of a single method). In some cases I might write

class Foo
BISECT = lambda { |x,y| (x+y)/2.0) }

def foo
  bar(someargs, &BISECT)
end

end

but in most cases, the logical place to put the ‘lambda’ is inline as a
block:

class Foo
def foo
bar(someargs) { |x,y| (x+y)/2.0) }
end
end

If ‘bisect’ were are large piece of code then I might implement this as
a separate method, or even a class.

I think I can see advantages of the “keep it simple” approach. If there
are no choices to make between different ways of expressing the same
thing, then you can just go ahead and code it without thinking. But
then, people have also said here that Lisp has a comprehensive object
system, which in turn means you’d still have to choose between functions
and objects with methods.

Brian C. [email protected] writes:

}
argument, which is an Array object.

You could have written the lambda to take a single Array argument:

mean = lambda { |arg| arg.inject(0) …etc }

I don’t know enough about Lisp to say how Lisp resolves the same
dichotomy, but surely it must exist. That is, there must be a difference
between calling a function foo with a (list of) n arguments, and calling
a function foo with 1 argument which is itself a list?

At the function definition site, it’s the same, you can decide whether
you’ll take a single argument of type list, or several arguments that
will be treated like a list:

(defun unary-function (arguments)
(process arguments))

(defun variadic-function (&rest arguments)
(process arguments))

At the call site:

If you have a list: several arguments:
list-of-args 1 2 3

(unary-function list-of-args) (unary-function (list
1 2 3))
[x]
(apply (function variadic-function) list-of-args) (variadic-function 1
2 3)
[y]

x: you can always build a list with the variadic function LIST.

y: there’s a maximal number of arguments (implementation defined) that
can be passed to a function, therefore a limit on the length of the
list
that can be passed with APPLY.

Moreover, Common Lisp as much richer parameter specifications.
You can specify of course mandatory parameters, but in addition:

  • optional parameters,
  • keyword parameters,
  • rest parameters as above.

For both optional parameters and keyword parameters (which are also
optional), you can specify a default value.

For example:

(defun example (mandatory-1 mandatory-2
&optional optional-1
(optional-2 'default-value
optional-2-present)
&rest remaining-arguments-(including-keys)
&key key-1
(key-2 'default-value-2 key-2-present)
((:actual-key key-3) 'default-value-3
key-3-present)
&allow-other-keys)

(print mandatory-1)
(print mandatory-2)
(when optional-1 (print optional-1))
(when optional-2-present (print optional-2))
(print remaining-arguments-(including-keys))
(print key-1)
(when key-2-present (print key-2))
(when key-3-present (print key-3))
(values))

C/USER[20]> (example 'm1 'm2 'o1 'o2 :actual-key 'ak :key-1 'k1
:whatever 'you-want)

M1
M2
O1
O2
(:ACTUAL-KEY AK :KEY-1 K1 :WHATEVER YOU-WANT)
K1
AK

(In the case of macros, you can even specify recursive lists, to
deconstruct any syntax).

Brian C. wrote:

Mike G. wrote:

Brian C. wrote:

Yes, a variable holding a lambda is a different beast to a method. As
you said, methods are associated with objects, and lambdas are not.
Usually one suits the usage case better than the other.

I find the distinct behaviours of both to be very useful in practice.

Can you give an example of where the difference is “very useful”?

Well, as you know, blocks are roughly just in-line lambdas:

10.times { |x| puts x }

If by “roughly” you mean “not”, then yes. Blocks are not lambdas, they
are Procs.

I was thinking of the following properties of the method/lambda
difference:

(1) You can return directly from a method, even from inside blocks.

class Foo
def bar
10.times { |x| …
10.times { |y| …
return “foo” if baz(x,y)
}
}
end
end

Lambdas do not abort the enclosing method with ‘return’.

def lambda_test
func = lambda {
return
}
puts “before”
func.call
puts “after”
end

def proc_test
func = Proc.new {
return
}

puts “before”
func.call
puts “after”
end

lambda_test # => before
# after

proc_test # => before

The topic was about the problems arising from the syntactic difference
between methods and lambdas. You’ve changed gears to a generic
discussion about procs. My question is yet unaddressed: why is
func.call() or func[] or func.() “very useful” compared to func()? As I
mentioned, in every case I’ve found it to be a hassle, for the reasons
previously stated.

On Jan 12, 2009, at 11:22 PM, Mike G. wrote:

So a functional language is one tailed for programming in this manner:
using higher-order functions, reaching out with The Force. It is
awkward in Ruby, but not in functional languages which were designed
for
it.

And I suspect that programming in an object oriented manner is probably
awkward in a language designed for the functional approach.

I think it is worthwhile understanding different programming styles but
working against the grain of a language seems like a bad idea to me.

Your specific suggestion that ‘name()’ could be syntactic sugar for
Proc#call introduces an ambiguity in the language that I find
disconcerting.

a = 0
b = Proc.new { rand }

a # variable reference
a() # method invocation (self.a)

b # variable reference
b.call # block invocation via Proc#call
b() # method invocation (self.b)? or disguised Proc#call?

Gary W.

Gary W. wrote:

I think it is worthwhile understanding different programming styles but
working against the grain of a language seems like a bad idea to me.

Yet I have found small-scale use of functional concepts to be useful in
ruby, what I have (perhaps confusingly) called functional-style-in-ruby
(but not functional programming per se): liberal use of map, inject,
etc; avoiding unnecessary re-assignments to the same variable; avoiding
gratuitous side-effects; not caring about temporary objects (until an
efficiency concern is proven). The same applies to programming in
general.

Your specific suggestion that ‘name()’ could be syntactic sugar for
Proc#call introduces an ambiguity in the language that I find
disconcerting.

There is no ambiguity because, as I mentioned, locals are determined at
parse time. However notice I recanted the suggestion seven minutes
later in the post which immediately followed, for similar reasons.

I suspect that when a thread reaches a certain size, nobody actually
reads it.

Brian C. wrote:

You could have written the lambda to take a single Array argument:

This is another repeat of previous comments by others in this thread.
I’ll say for at least the third time now: the point is that the lambda
is given – you cannot change it.

Since the requisite attention has waned, it may be time to give up. But
I will try one more approach.

The idea of functional programming is to use higher-order functions to
get the job done. It’s like using The Force. You aren’t allowed to
pick up the rock. You have to concentrate, reach out with The Force,
and make it rise into the air without touching it. You can only use
higher-order functions.

Initially, you may not be very productive compared to others who are
using their hands to move rocks. Eventually, however, you are able to
move 100 rocks at once, far surpassing your manual-labor counterparts.

The analogy is exaggerated, but it serves to convey the idea.

Say we wish to add these pairs together,

data = [[1,2], [3,4], [5, 6]]

Here is the manual approach – grabbing the rock with your hands:

data.map { |x, y| x + y } #=> [3, 7, 11]

The only problem is that it’s very specific to this one case. We’ve
used ‘map’, which is a heck of a lot better than not using it, but the
code could still be more general.

Now let’s try using The Force. First we need some helper functions.

def splatter(func)
lambda { |args| func.call(*args) }
end

def binder(method)
lambda { |*args| method.bind(args[0]).call(*args[1…-1]) }
end

All right, here we go:

data.map(&splatter(binder(Fixnum.instance_method(:+))))
#=> [3, 7, 11]

Note how general this is. I can use any method from anywhere (not just
from Fixnum), with any set of data. This even works with the ‘mean’
function which failed before,

mean = lambda { |*args|
(args.inject(0) { |acc, x| acc + x })/args.size.to_f
}
[[1,2,3], [4,5,6,7]].map(&splatter(mean))
#=> [2.0, 5.5]

So a functional language is one tailed for programming in this manner:
using higher-order functions, reaching out with The Force. It is
awkward in Ruby, but not in functional languages which were designed for
it.

Unfortunately the only way to really understand what I mean is to
practice programming in a functional language. The basics of Haskell
can be learned pretty quickly, I think. I thought this was a fun book:
http://learnyouahaskell.com .

Mike G. [email protected] writes:

The topic was about the problems arising from the syntactic difference
between methods and lambdas. You’ve changed gears to a generic
discussion about procs. My question is yet unaddressed: why is
func.call() or func[] or func.() “very useful” compared to func()? As I
mentioned, in every case I’ve found it to be a hassle, for the reasons
previously stated.

The reason is because Ruby is a lisp-2. The same name can be used to
designate both a method and a variable. So you need two syntaxes, to
make reference to the method of a name, or to the variable. When the
variable contains normal values,

(def f
:function
end)

f = (lambda { :variable })

irb(main):064:0> [ f , (f []) , (method :f) , (f ()) ]
[ f , (f []) , (method :f) , (f ()) ]
[#Proc:0x00306ed4@:51(irb), :variable, #<Method: Object#f>, :function]

In Common Lisp, which is a lisp-2 too, we use FUNCALL to call functions
stored in variables:

(defun f () :function)
(defvar f (lambda () :variable))

C/USER[24]> (list f (funcall f) (function f) (f))
(# :VARIABLE # :FUNCTION)

Pascal J. Bourguignon wrote:

Mike G. [email protected] writes:

Why is func.call() or func[] or func.() “very useful” compared to
func()? As I mentioned, in every case I’ve found it to be a
hassle, for the reasons previously stated.

The reason is because Ruby is a lisp-2. The same name can be used to
designate both a method and a variable. So you need two syntaxes, to
make reference to the method of a name, or to the variable.

No, that’s not the reason. It is because Ruby allows method invocation
without parens. Therefore parens cannot be used to unambiguously
“dereference” a function. The case in point is Python,

class X:
def f(self):
return “foo”

x = X()
g = x.f
g() #=> “foo”

triple = lambda z: 3*z
triple(2) #=> 6

We all know the Ruby version, but just for good measure –

class X
def f
“foo”
end
end

x = X.new
g = x.method(:f)
g.call #=> “foo”

triple = lambda { |z| 3*z }
triple.call(2) #=> 6

Mike G. wrote:

Yet I have found small-scale use of functional concepts to be useful in
ruby, what I have (perhaps confusingly) called functional-style-in-ruby
(but not functional programming per se): liberal use of map, inject,
etc; avoiding unnecessary re-assignments to the same variable; avoiding
gratuitous side-effects; not caring about temporary objects (until an
efficiency concern is proven). The same applies to programming in
general.

I don’t think you’ll find any disagreement there. One of the things I
like about Ruby is that it’s very easy to pick up in an imperative
style, and then one by one, as you “get” each new concept, you can start
incorporating them in your programs. (for -> each -> map -> inject ->
…etc)

Ruby makes a nice playground for exploring functional concepts (I
finally “got” the Y combinator after converting it into Ruby), but the
lack of tail recursion and the like means that it is not an efficient
environment for large scale use of them. Mapping the problem domain into
classes and methods works much better.

However, we can probably agree that Ruby does make small imperative
programs very easy to write. For example, a basic imperative construct
is “do x, then do y, then do z”. In Ruby I just write

x
y
z

In LISP, “do x” is “(x)”, but I couldn’t write

(x)
(y)
(z)

or even

(
  (x)
  (y)
  (z)
)

which will most likely bomb out horribly at runtime (**), but

(begin
  (x)
  (y)
  (z)
)

That’s a special form and a lot of brackets to do something “simple”.

But on the other hand, for someone coming from a functional background,
they might say that the whole concept of “do x, then do y” is rarely if
ever needed. Why would you evaluate something, only to throw it away?

Different languages suit different people’s thought processes.

Regards,

Brian.

(**) I believe this is roughly equivalent to: x.call(y,z)

Brian C. wrote:

Different languages suit different people’s thought processes.

But the different languages shape the thought processes.

A programmer should have at least some experience using a functional
language (Haskell, ML, OCaml, or similar) and a logic language
(Prolog). (Most everyone is already familiar with object-oriented and
imperative languages.)

The danger of staying in the dark is not so much that you’ll miss out
on the language, but that you’ll miss out on the thought processes.

If Matz hadn’t been a Lisp programmer when he wrote Ruby, I guarantee
that Ruby would have turned out worse.

Gary W. wrote:

Which I interpreted as support for the name() syntax for function
application.

I pointed you to the post where I called the idea silly. Are you
looking for a more dramatic act of contrition?

Mike G. wrote:

Brian C. wrote:

Different languages suit different people’s thought processes.

But the different languages shape the thought processes.

Of course - and dabbling with Lisp and Erlang have undoubtedly been
useful. That doesn’t mean I want to abandon Ruby and change to Lisp.

That would be a big investment, for example:

  • analysing and choosing which dialect and implementation of Lisp to use
  • learning a whole new set of standard libraries
  • learning a whole new set of tools and frameworks (e.g. unit testing)
  • probably even learning a new editor too

and I am not convinced there would be significant payback in either
productivity or “fun”.

OTOH, I can certainly see applications where it would be worthwhile
moving to Erlang - using the CSP model for distributed processing. Of
course, I expect now to be told that Lisp has such capabilities as well
:slight_smile:

Mike G. [email protected] writes:

No, that’s not the reason. It is because Ruby allows method invocation
without parens. Therefore parens cannot be used to unambiguously
“dereference” a function.

It wouldn’t matter if we had not to distinguish calling a named
function from calling a function stored in a variable.

So we could say that we’re in violent agreement.

On Jan 13, 2009, at 1:37 AM, Mike G. wrote:

Your specific suggestion that ‘name()’ could be syntactic sugar for
Proc#call introduces an ambiguity in the language that I find
disconcerting.

There is no ambiguity because, as I mentioned, locals are determined
at
parse time. However notice I recanted the suggestion seven minutes
later in the post which immediately followed, for similar reasons.

I should have quoted it, but I was responding to your very-late-in-the-
conversation
comment:

The topic was about the problems arising from the syntactic difference
between methods and lambdas. You’ve changed gears to a generic
discussion about procs. My question is yet unaddressed: why is
func.call() or func[] or func.() “very useful” compared to func()?
As I
mentioned, in every case I’ve found it to be a hassle, for the reasons
previously stated.

Which I interpreted as support for the name() syntax for function
application.

Presumably you would want function application to be available to any
expression though, not just to a local variable, and so I think you
are still stuck with
the fact that parens can’t be unambiguously interpreted during
parsing. You would
need some precedence rule.

a = object.generate_lambda
a() # apply, because parser knows that a is a variable not a method
call

object.generate_lambda() # call, then apply or just a zero
argument call?
(object.generate_lambda)() # call, then apply

I’m not arguing that it isn’t possible to come up with some rules that
would make it possible
for method/function application to be done via parens. It just seems
like an unnecessary
complication.

Gary W.

Hi –

On Wed, 14 Jan 2009, Pascal J. Bourguignon wrote:

designate both a method and a variable. So you need two syntaxes, to
make reference to the method of a name, or to the variable.

No, that’s not the reason. It is because Ruby allows method invocation
without parens. Therefore parens cannot be used to unambiguously
“dereference” a function.

It wouldn’t matter if we had not to distinguish calling a named
function from calling a function stored in a variable.

But what would this be:

f = lambda {}
def f; end
f()

I don’t think you can express all of Ruby’s object model and
assignment semantics if you remove the message-sending semantics from
Proc objects. That’s the problem: not when it’s one or the other, but
when it’s both. (I’m not a big fan of the magical dereferencing of
Procs, I admit, but I’m not sure how it would work even if it were
done.)

David


David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Coming in 2009: The Well-Grounded Rubyist (The Well-Grounded Rubyist)

http://www.wishsight.com => Independent, social wishlist management!