On 14 Jun 2009, at 14:09, Niels Grewe wrote:

> On Sat, Jun 13, 2009 at 10:35:44AM +0100, David Chisnall wrote:
>> Good catch on the nil test in map.
>
> Right, I somehow forgot to mention that in the email.
>
>> Did you try running your test program?  It references a variable
>> 'lower' which doesn't exist, so it shouldn't even compile...
>
> My bad. I manually changed variable names before attaching the code.
> "lower" should always be "input": %s/lower/input/g
>
>
>> I expect to use a fold method like this:
>>
>> id input = A(@"a", @"b", @"c");
>> [ETTranscript show: [[input fold] stringByAppendingString: @"letters:
>> "]];
>>
>> I would then get the output:
>>
>> letters: abc
>
> I personally find that counter-intuitive. The selector you pass to the
> proxy object seems represent a folding function, which should take
> as arguments the accumulator and an element of the collection to  
> operate
> upon (at least). You seem to take @"letters: " as the initial
> value of the accumulator. I'd then figure that the receiver will be
> element to operate on.  So on casual reading the code seems to say
> 'fold input by appending @"letters: " to each element', which is not
> what you want.
> Of course, intuitions vary wildly among people, so feel free to
> disagree.

This matches how fold works in most functional languages; it takes a  
function and an initial value for the accumulator.

> But you got another point here: I totally disregarded that one might
> want to set the initial value of the accummulator. (It's not my usual
> usage pattern, I usally set those to something irrelevant). So what
> about writing the above like this:
>
> [[input fold: @"letters: "] stringByAppendingString:  
> (NSString*)input];
>
> Reusing the input array signifies that you want to use the elements of
> the input array at that position of the method. I'm using that
> mysterious (and clumsy, I admit it) selfArgs array to determine the
> positions at which to replace the reference to the whole array with a
> reference to the element in question.

I'm not sure why you would do this.  Wouldn't you get the same effect  
by passing nil as the initial value of the accumulator?

> As an additional benefit you can then use more complex methods as
> folding functions. Suppose NSString implemented
> -stringByAppendingString:andString:, you could easily do stuff like
> this:
>
> [[input fold: @"letters: "] stringByAppendingString: @"-"
>                                          andString:(NSString*)input];
>
> Wich produces the result "letters: -a-b-c" [0] and would, as far as i
> can see, not feasible with the implementation you are suggesting. This
> approach is still a little bit arkward since if you really want to use
> the input array as an argument to the method you're folding with then
> you'd need to copy it.

This looks really horrible.  The point of higher-order messaging is to  
improve readability; if we're not doing that then there is no point in  
bothering at all.

> Additionally, I was going to reply to Günther's enquiry about blocks
> that I chose not to use them since they require clang, but since  
> you're
> just proposing to switch to clang as the default compiler for Étoilé,
> implementing this whole higher order messaging stuff with blocks would
> probably be okay, wouldn't it?

HOM and blocks are orthogonal.  We have an equivalent of -map that  
takes a block as an argument already, and a few other similar  
methods.  It's a question of conciseness.  Which of these do you find  
more readable:

[[array map] stringByAppendingString: @"suffix"];
[array map: ^(NSString *a) { return [a stringByAppendingString:  
@"suffix"]; }];

Or, the SmallTalk equivalents:

array map stringByAppendingString: 'suffix'.
array map: [ :x | x stringByAppendingString: 'suffix' ].

Of course, if the block has more than a single statement in it, the  
version taking a block as an argument is more expressive, but for  
simple cases it is more complicated.  As always, it's about picking  
the right tool for the job.  HOM on collections is for making the  
simple, common, cases easy.  Blocks are for making the general case  
work.

David
_______________________________________________
Etoile-dev mailing list
Etoile-dev@gna.org
https://mail.gna.org/listinfo/etoile-dev

Reply via email to