Jump to page: 1 2
Thread overview
Functional Programming with D
Apr 13, 2013
qznc
Apr 13, 2013
Vladimir Panteleev
Apr 13, 2013
qznc
Apr 13, 2013
Timon Gehr
Apr 13, 2013
qznc
Apr 13, 2013
bearophile
Apr 13, 2013
qznc
Apr 14, 2013
Ali Çehreli
Apr 14, 2013
Chris Cain
Apr 14, 2013
qznc
Apr 14, 2013
anonymous
Apr 14, 2013
Ali Çehreli
Aug 28, 2015
Kingsley
Aug 28, 2015
Russel Winder
April 13, 2013
I wrote a small article to summarize D's suitability for functional programming.

http://beza1e1.tuxen.de/articles/functional_D.html

Feedback welcome! :)
April 13, 2013
On Saturday, 13 April 2013 at 12:29:29 UTC, qznc wrote:
> Feedback welcome! :)

You wrote:

> While there is no syntactic sugar,

What about lambdas?

http://dlang.org/expression.html#Lambda
April 13, 2013
Sat, 13 Apr 2013 15:03:51 +0200: Vladimir Panteleev wrote
> On Saturday, 13 April 2013 at 12:29:29 UTC, qznc wrote:
>> While there is no syntactic sugar,
> 
> What about lambdas?
> 
> http://dlang.org/expression.html#Lambda

Oh. I forgot about those. Thanks!

The syntactic sugar seems to be quite diverse, since most of the FunctionLiteral is optional. As far as I understand the docs, all the following forms are valid?

auto square1 = function int (int x) { return x*x; };
auto square2 = function (int x) { return x*x; };
auto square3 = (int x) { return x*x; };
auto square4 = int (int x) { return x*x; };
auto square5 = (int x) => x*x;
auto square6 = x => x*x;
April 13, 2013
On 04/13/2013 05:25 PM, qznc wrote:
> Sat, 13 Apr 2013 15:03:51 +0200: Vladimir Panteleev wrote
>> On Saturday, 13 April 2013 at 12:29:29 UTC, qznc wrote:
>>> While there is no syntactic sugar,
>>
>> What about lambdas?
>>
>> http://dlang.org/expression.html#Lambda
>
> Oh. I forgot about those. Thanks!
>
> The syntactic sugar seems to be quite diverse, since most of the
> FunctionLiteral is optional. As far as I understand the docs, all the
> following forms are valid?
>
> auto square1 = function int (int x) { return x*x; };

yes.

> auto square2 = function (int x) { return x*x; };

yes.

> auto square3 = (int x) { return x*x; };

yes.

> auto square4 = int (int x) { return x*x; };

no.

> auto square5 = (int x) => x*x;

yes.

> auto square6 = x => x*x;
>

no. (valid grammar, but you need some type annotation.)

But there are more, like function(int x)=>x*x.
April 13, 2013
Sat, 13 Apr 2013 17:46:10 +0200: Timon Gehr wrote

> On 04/13/2013 05:25 PM, qznc wrote:
>> Sat, 13 Apr 2013 15:03:51 +0200: Vladimir Panteleev wrote
>>> On Saturday, 13 April 2013 at 12:29:29 UTC, qznc wrote:
>>>> While there is no syntactic sugar,
>>>
>>> What about lambdas?
>>>
>>> http://dlang.org/expression.html#Lambda
>>
>> Oh. I forgot about those. Thanks!
>>
>> The syntactic sugar seems to be quite diverse, since most of the FunctionLiteral is optional. As far as I understand the docs, all the following forms are valid?
>>
>> auto square1 = function int (int x) { return x*x; };
> 
> yes.
> 
>> auto square2 = function (int x) { return x*x; };
> 
> yes.
> 
>> auto square3 = (int x) { return x*x; };
> 
> yes.
> 
>> auto square4 = int (int x) { return x*x; };
> 
> no.
> 
>> auto square5 = (int x) => x*x;
> 
> yes.
> 
>> auto square6 = x => x*x;
>>
>>
> no. (valid grammar, but you need some type annotation.)
> 
> But there are more, like function(int x)=>x*x.

That one is not documented in the grammar. A Lambda does not start with "function" and a FunctionLiteral does not contain "=>". What is it?
April 13, 2013
Sat, 13 Apr 2013 15:03:51 +0200: Vladimir Panteleev wrote

> On Saturday, 13 April 2013 at 12:29:29 UTC, qznc wrote:
>> Feedback welcome! :)
> 
> You wrote:
> 
>> While there is no syntactic sugar,
> 
> What about lambdas?
> 
> http://dlang.org/expression.html#Lambda

I added them to the article and acknowledged you. Thanks!
April 13, 2013
Timon Gehr:

>> auto square6 = x => x*x;
>>
>
> no. (valid grammar, but you need some type annotation.)

In theory a syntax like:

alias square6 = x => x * x;

Can be a shorthand for a template function like:

auto square6(T0)(T0 x) { return x * x; }

Bye,
bearophile
April 14, 2013
On 04/13/2013 05:29 AM, qznc wrote:
> I wrote a small article to summarize D's suitability for functional
> programming.
>
> http://beza1e1.tuxen.de/articles/functional_D.html
>
> Feedback welcome! :)
>

Nice article; thanks. :)

Some quotes from the article and some notes:

1) "can qualify variables as immutable, which is similiar to C's const"

D's immutable is similar to C's const only when we are talking about values:

    const int c_i = 42;    // in C
    immutable d_i = 42;    // in D

When it is a reference though, not immutable but D's const is similar to C's const. Otherwise, there is the following difference:

    // in C: I have no idea whether c is immutable
    void foo(const int * c);

    // in D: I know d is immutable
    void foo(immutable const ref d);

(Actually, not only I "know", but I "demand" that d is immutable.)

2) "if you have a function which does not mutate an argument, then qualify it const, but not immutable"

I had arrived the same conclusion (and have been spreading it too :)).

Actually, the choice is not that clear: If the function is going to need an immutable copy of a reference parameter anyway, then it is better that it goes ahead and takes an immutable reference parameter:

    void foo(immutable(int)[] numbers);

The benefit is, if the caller already has an immutable slice, then that slice gets passed as the argument. That is the fastest... On the other hande, if the caller does not have an immutable slice, then the caller makes one and passes the new copy. Nothing is lost: The copy that the function would have to make has been made by caller.

Although that seems like an implementation detail of the function leaking out, and it really is, it is not that bad if we view it like this: What is happening is that the function is working with its caller to get more performance.

3) "D does not allow you to cast something to immutable"

I think you mean "no implicit conversion" because it is not true if we take what you said literally:

    auto a = [ 1, 2 ];
    immutable i = cast(immutable)a;  // dangerous

    a[0] = 42;
    assert(i[0] == 42);  // oops: immutable element has changed!

Ali

April 14, 2013
On Sunday, 14 April 2013 at 00:38:24 UTC, Ali Çehreli wrote:
> 3) "D does not allow you to cast something to immutable"
>
> I think you mean "no implicit conversion" because it is not true if we take what you said literally:
>
>     auto a = [ 1, 2 ];
>     immutable i = cast(immutable)a;  // dangerous
>
>     a[0] = 42;
>     assert(i[0] == 42);  // oops: immutable element has changed!
>
> Ali

Also, the usual way to do this (if you're doing it _properly_, this is still vulnerable to being misused) is using `assumeUnique` ... the "requirements" for that function are implied by its name: it really wants a unique reference that will be transformed into an immutable.

```
import std.exception : assumeUnique;

static immutable size_t base = cast(size_t) ('z' - 'a') + 1;

// Remember:
// alias string = immutable(char)[]
string numToString(size_t length, size_t num) {
    char[] result = new char[](length);
    foreach_reverse(ref e; result) {
        auto digit = num % base;
        e = cast(char)('a' + digit);
        num /= base;
    }

    // OK because no other references exist
    return assumeUnique(result);
}
```
April 14, 2013
Sat, 13 Apr 2013 17:38:24 -0700: Ali Çehreli wrote

> On 04/13/2013 05:29 AM, qznc wrote:
>> I wrote a small article to summarize D's suitability for functional programming.
>>
>> http://beza1e1.tuxen.de/articles/functional_D.html
>>
>> Feedback welcome! :)
>>
>>
> Nice article; thanks. :)
> 
> Some quotes from the article and some notes:
> 
> 1) "can qualify variables as immutable, which is similiar to C's const"
> 
> D's immutable is similar to C's const only when we are talking about values:
> 
>      const int c_i = 42;    // in C immutable d_i = 42;    // in D
> 
> When it is a reference though, not immutable but D's const is similar to C's const. Otherwise, there is the following difference:
> 
>      // in C: I have no idea whether c is immutable void foo(const int *
>      c);
> 
>      // in D: I know d is immutable void foo(immutable const ref d);
> 
> (Actually, not only I "know", but I "demand" that d is immutable.)

The C variant is an mutable pointer to an immutable int. What is not to know about that?

> 2) "if you have a function which does not mutate an argument, then qualify it const, but not immutable"
> 
> I had arrived the same conclusion (and have been spreading it too :)).
> 
> Actually, the choice is not that clear: If the function is going to need an immutable copy of a reference parameter anyway, then it is better that it goes ahead and takes an immutable reference parameter:
> 
>      void foo(immutable(int)[] numbers);
> 
> The benefit is, if the caller already has an immutable slice, then that slice gets passed as the argument. That is the fastest... On the other hande, if the caller does not have an immutable slice, then the caller makes one and passes the new copy. Nothing is lost: The copy that the function would have to make has been made by caller.
> 
> Although that seems like an implementation detail of the function leaking out, and it really is, it is not that bad if we view it like this: What is happening is that the function is working with its caller to get more performance.

I agree with you. However, it is too much detail for the article.

> 3) "D does not allow you to cast something to immutable"
> 
> I think you mean "no implicit conversion" because it is not true if we take what you said literally:
> 
>      auto a = [ 1, 2 ];
>      immutable i = cast(immutable)a;  // dangerous
> 
>      a[0] = 42;
>      assert(i[0] == 42);  // oops: immutable element has changed!

I clarified this in the article. Thanks for pointing it out. :)

« First   ‹ Prev
1 2