caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] List.fold_left vs. Hashtbl.fold
@ 2012-11-28  4:40 William Smith
  2012-11-28 16:17 ` Lukasz Stafiniak
                   ` (3 more replies)
  0 siblings, 4 replies; 17+ messages in thread
From: William Smith @ 2012-11-28  4:40 UTC (permalink / raw)
  To: OCAML

List.fold_left expects the List as the 3rd parameter with the second 
parameter being the initial value.

Hashtbl.fold expects the Hasthbl as the second parameter with the 3rd 
parameter being the initial value... just the opposite of List.fold_left.

Is there a reason for this difference?   I'm having trouble remembering 
which goes which way.   If it's not a historical accident, I'd like to 
have a understanding of why they are different to help me know which is 
which.

Thanks,

Bill

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] List.fold_left vs. Hashtbl.fold
  2012-11-28  4:40 [Caml-list] List.fold_left vs. Hashtbl.fold William Smith
@ 2012-11-28 16:17 ` Lukasz Stafiniak
  2012-11-28 16:25   ` Malcolm Matalka
  2012-11-28 16:21 ` David House
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 17+ messages in thread
From: Lukasz Stafiniak @ 2012-11-28 16:17 UTC (permalink / raw)
  To: William Smith; +Cc: OCAML

I have this problem too. Look _very closely_ at List.fold_left and
List.fold_right. Hashtbl.fold should pretend to be like
List.fold_left, because it is not supposed to preserve the structure
of the underlying data structure in its computation, and it should be
tail-recursive.

On Wed, Nov 28, 2012 at 5:40 AM, William Smith <bills@wwayneb.com> wrote:
> List.fold_left expects the List as the 3rd parameter with the second
> parameter being the initial value.
>
> Hashtbl.fold expects the Hasthbl as the second parameter with the 3rd
> parameter being the initial value... just the opposite of List.fold_left.
>
> Is there a reason for this difference?   I'm having trouble remembering
> which goes which way.   If it's not a historical accident, I'd like to have
> a understanding of why they are different to help me know which is which.
>
> Thanks,
>
> Bill

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] List.fold_left vs. Hashtbl.fold
  2012-11-28  4:40 [Caml-list] List.fold_left vs. Hashtbl.fold William Smith
  2012-11-28 16:17 ` Lukasz Stafiniak
@ 2012-11-28 16:21 ` David House
  2012-11-29  1:06   ` Francois Berenger
  2012-11-28 16:42 ` Oliver Bandel
       [not found] ` <CAPFanBG04BiwJuPkV80__Ondmg1N8OEg4DokiXqDReg3ycNBdA@mail.gmail.com>
  3 siblings, 1 reply; 17+ messages in thread
From: David House @ 2012-11-28 16:21 UTC (permalink / raw)
  To: William Smith; +Cc: OCAML

This is a perfect example of why we wrote the core library:

  https://bitbucket.org/yminsky/ocaml-core/wiki/Home

In core, most of the iteration functions take their closure argument
as a labelled ~f. So you can say List.fold_left my_list ~f:my_func, or
List.fold_left ~f:my_func my_list.

This tiny syntactic cost allows you lay out code much more logically:
sometime you have a big long list, so you don't want the name of the
function lost somewhere, way down the page. Sometimes it's the other
way round, and you have a bit lambda that you're folding with, but you
don't want the name of the list to be some anonymous bit of text a
very long way away from the word "fold".

On Wed, Nov 28, 2012 at 4:40 AM, William Smith <bills@wwayneb.com> wrote:
> List.fold_left expects the List as the 3rd parameter with the second
> parameter being the initial value.
>
> Hashtbl.fold expects the Hasthbl as the second parameter with the 3rd
> parameter being the initial value... just the opposite of List.fold_left.
>
> Is there a reason for this difference?   I'm having trouble remembering
> which goes which way.   If it's not a historical accident, I'd like to have
> a understanding of why they are different to help me know which is which.
>
> Thanks,
>
> Bill
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] List.fold_left vs. Hashtbl.fold
  2012-11-28 16:17 ` Lukasz Stafiniak
@ 2012-11-28 16:25   ` Malcolm Matalka
  0 siblings, 0 replies; 17+ messages in thread
From: Malcolm Matalka @ 2012-11-28 16:25 UTC (permalink / raw)
  To: Lukasz Stafiniak; +Cc: OCAML, William Smith

[-- Attachment #1: Type: text/plain, Size: 1297 bytes --]

Jane St Core uses labeled arguments to avoid this issue, worth considering
if you can.
On Nov 28, 2012 5:18 PM, "Lukasz Stafiniak" <lukstafi@gmail.com> wrote:

> I have this problem too. Look _very closely_ at List.fold_left and
> List.fold_right. Hashtbl.fold should pretend to be like
> List.fold_left, because it is not supposed to preserve the structure
> of the underlying data structure in its computation, and it should be
> tail-recursive.
>
> On Wed, Nov 28, 2012 at 5:40 AM, William Smith <bills@wwayneb.com> wrote:
> > List.fold_left expects the List as the 3rd parameter with the second
> > parameter being the initial value.
> >
> > Hashtbl.fold expects the Hasthbl as the second parameter with the 3rd
> > parameter being the initial value... just the opposite of List.fold_left.
> >
> > Is there a reason for this difference?   I'm having trouble remembering
> > which goes which way.   If it's not a historical accident, I'd like to
> have
> > a understanding of why they are different to help me know which is which.
> >
> > Thanks,
> >
> > Bill
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>

[-- Attachment #2: Type: text/html, Size: 1922 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] List.fold_left vs. Hashtbl.fold
  2012-11-28  4:40 [Caml-list] List.fold_left vs. Hashtbl.fold William Smith
  2012-11-28 16:17 ` Lukasz Stafiniak
  2012-11-28 16:21 ` David House
@ 2012-11-28 16:42 ` Oliver Bandel
  2012-11-28 17:11   ` Adrien
       [not found] ` <CAPFanBG04BiwJuPkV80__Ondmg1N8OEg4DokiXqDReg3ycNBdA@mail.gmail.com>
  3 siblings, 1 reply; 17+ messages in thread
From: Oliver Bandel @ 2012-11-28 16:42 UTC (permalink / raw)
  To: William Smith; +Cc: OCAML

[-- Attachment #1: Type: text/plain, Size: 1995 bytes --]

As both functions are working different, I,think from some reasoing about it, it might become logical ....

http://www.cs.cornell.edu/courses/cs3110/2011sp/recitations/rec05.htm

Even there is explained how which functionsmlooks like if implemented,
the reason is not obvious.
I think there might be a logical explanation for this,
but to be honest I also have no handy rule of thumb for it.

But both functions look different in the application of the non-tail argument,
so I think this is  the reason for it (if not by accident;-))

If you find an easy way to remember it from the above mentioned doc, please let me know.
athe üroblem there in the doc is, that the program structure is cluttered by type annotations.

But maybe writng down how an application would look like,
applying the function by hand, would offer the mysteries.

I just was to lazy for this until now, and just accepted the order.
So I also need to look up the order in the manual.

But from the different non-tail part of the functions I would think, it is possible to find a reason.
After you find it, you maybe dont want to have a unified API ;-)

Ciao,
   Oliver


Am 28.11.2012 um 05:40 schrieb William Smith <bills@wwayneb.com>:

> List.fold_left expects the List as the 3rd parameter with the second parameter being the initial value.
> 
> Hashtbl.fold expects the Hasthbl as the second parameter with the 3rd parameter being the initial value... just the opposite of List.fold_left.
> 
> Is there a reason for this difference?   I'm having trouble remembering which goes which way.   If it's not a historical accident, I'd like to have a understanding of why they are different to help me know which is which.
> 
> Thanks,
> 
> Bill
> 
> -- 
> Caml-list mailing list.  Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs

[-- Attachment #2: Type: text/html, Size: 9761 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] List.fold_left vs. Hashtbl.fold
  2012-11-28 16:42 ` Oliver Bandel
@ 2012-11-28 17:11   ` Adrien
  2012-11-28 17:41     ` Virgile Prevosto
  0 siblings, 1 reply; 17+ messages in thread
From: Adrien @ 2012-11-28 17:11 UTC (permalink / raw)
  To: Oliver Bandel; +Cc: William Smith, OCAML

Well, MoreLabels.Hashtbl has
  val  fold  : f:(key:'a -> data:'b -> 'c -> 'c) -> ('a, 'b) t -> init:'c -> 'c

-- 
Adrien Nader

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Caml-list] List.fold_left vs. Hashtbl.fold
       [not found] ` <CAPFanBG04BiwJuPkV80__Ondmg1N8OEg4DokiXqDReg3ycNBdA@mail.gmail.com>
@ 2012-11-28 17:25   ` Gabriel Scherer
  2012-11-28 17:37     ` Lukasz Stafiniak
  0 siblings, 1 reply; 17+ messages in thread
From: Gabriel Scherer @ 2012-11-28 17:25 UTC (permalink / raw)
  To: caml users

(Sorry for duplicate send.)

There are two exported way to fold over lists:
  fold_left : ('acc -> 'e -> 'acc) -> ('acc -> 'e list -> 'acc)
  fold_right : ('e -> 'acc -> 'acc) -> ('e list -> 'acc -> 'acc)

The _left and _right suffixes indicate whether the "accumulator"
argument (the partial result of what has been folded so far) is passed
as the left or the right parameter of the function argument: ('acc ->
'e -> 'acc) for left, ('e -> 'acc -> 'acc) for right. The return type
of fold then lifts this argument type from processing an element to
processing the whole list: the initial 'acc value for is passed "on
the left" for fold_left (before the list argument), "on the right" for
fold_right (after the list argument).

That's for the type. Regarding the implementation, fold_left applies
the argument function starting from "the left" (the beginning) of the
list first, while fold_right begins "on the right" (at the end): for
some infix operator (++) :
  fold_left (++) init [x; y; z]     is  ((init ++ x) ++ y) ++ z
  fold_right (++) [x; y; z] init   is (x ++ (y ++ (z ++ init)))
(The evaluation "begins" in the innermost nested parentheses)

Those two iterations techniques are available for linear data
structures (those that essentially look like lists). For more general
algebraic datatypes there is a canonical "folding" method, that
happens to coincide with fold_right on lists. The reason why
fold_right is "canonical" is that it turns the list
  x :: (y :: (z :: []))
into
  (x ++ (y ++ (z ++ init)))
replacing each constructor with a passed-in operator.

This means that fold_left may not exist for arbitrary data structure
(think of binary trees), while fold_right is rather universal. Other
folding functions in the standard library (in Set and Map in
particular, but in Hashtbl as well) have therefore taken inspiration
from the fold_right structure, rather than fold_left.

On Wed, Nov 28, 2012 at 5:40 AM, William Smith <bills@wwayneb.com> wrote:
>
> Hashtbl.fold expects the Hasthbl as the second parameter with the 3rd
> parameter being the initial value... just the opposite of List.fold_left.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] List.fold_left vs. Hashtbl.fold
  2012-11-28 17:25   ` Gabriel Scherer
@ 2012-11-28 17:37     ` Lukasz Stafiniak
  0 siblings, 0 replies; 17+ messages in thread
From: Lukasz Stafiniak @ 2012-11-28 17:37 UTC (permalink / raw)
  To: Gabriel Scherer; +Cc: caml users

On Wed, Nov 28, 2012 at 6:25 PM, Gabriel Scherer
<gabriel.scherer@gmail.com> wrote:
>
> This means that fold_left may not exist for arbitrary data structure
> (think of binary trees), while fold_right is rather universal. Other
> folding functions in the standard library (in Set and Map in
> particular, but in Hashtbl as well) have therefore taken inspiration
> from the fold_right structure, rather than fold_left.

This is right, you get my "upvote". But Set and Map do not intend to
expose the structure of the underlying data structure to the folding
computation. The folds of Set and Map traverse the elements in a
sequential order. They could be a deforested variant of List.fold_left
composed with Set.elements.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] List.fold_left vs. Hashtbl.fold
  2012-11-28 17:11   ` Adrien
@ 2012-11-28 17:41     ` Virgile Prevosto
  2012-11-29  0:07       ` Jacques Garrigue
  0 siblings, 1 reply; 17+ messages in thread
From: Virgile Prevosto @ 2012-11-28 17:41 UTC (permalink / raw)
  To: OCAML

2012/11/28 Adrien <camaradetux@gmail.com>:
> Well, MoreLabels.Hashtbl has
>   val  fold  : f:(key:'a -> data:'b -> 'c -> 'c) -> ('a, 'b) t -> init:'c -> 'c
>

Fair enough, but there's no label (say acc) to the last argument of f
(nor for the table itself), so you can't really permute the current
element and the accumulator in the argument list.

-- 
E tutto per oggi, a la prossima volta
Virgile

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] List.fold_left vs. Hashtbl.fold
  2012-11-28 17:41     ` Virgile Prevosto
@ 2012-11-29  0:07       ` Jacques Garrigue
  0 siblings, 0 replies; 17+ messages in thread
From: Jacques Garrigue @ 2012-11-29  0:07 UTC (permalink / raw)
  To: Virgile Prevosto; +Cc: OCAML

On 2012/11/29, at 1:41, Virgile Prevosto <virgile.prevosto@m4x.org> wrote:

> 2012/11/28 Adrien <camaradetux@gmail.com>:
>> Well, MoreLabels.Hashtbl has
>>  val  fold  : f:(key:'a -> data:'b -> 'c -> 'c) -> ('a, 'b) t -> init:'c -> 'c
>> 
> 
> Fair enough, but there's no label (say acc) to the last argument of f
> (nor for the table itself), so you can't really permute the current
> element and the accumulator in the argument list.

Not true for fold itself: no label is equivalent to the empty label,
so if you write "fold t" you are partially applying to the table.
On the other hand, changing parameter order is not allowed
in functions passed as argument. So reordering of arguments to
f is not automatic. But at least it ensures that you do not get it wrong.

Also a good reason to use labels in fold is when both remaining arguments
have the same type:

  List.fold_left (fun l x -> if List.mem x l then l else x::l)

since the accumulator and the input list have the same type, I'm always
afraid of getting them wrong (ending up doing nothing).

	Jacques Garrigue

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] List.fold_left vs. Hashtbl.fold
  2012-11-28 16:21 ` David House
@ 2012-11-29  1:06   ` Francois Berenger
  0 siblings, 0 replies; 17+ messages in thread
From: Francois Berenger @ 2012-11-29  1:06 UTC (permalink / raw)
  To: caml-list

On 11/29/2012 01:21 AM, David House wrote:
> This is a perfect example of why we wrote the core library:
>
>    https://bitbucket.org/yminsky/ocaml-core/wiki/Home
>
> In core, most of the iteration functions take their closure argument
> as a labelled ~f. So you can say List.fold_left my_list ~f:my_func, or
> List.fold_left ~f:my_func my_list.

For those who only need labels, there are:

Module MoreLabels.Hashtbl
http://caml.inria.fr/pub/docs/manual-ocaml/libref/MoreLabels.Hashtbl.html

and

Module ListLabels
http://caml.inria.fr/pub/docs/manual-ocaml/libref/ListLabels.html

> This tiny syntactic cost allows you lay out code much more logically:
> sometime you have a big long list, so you don't want the name of the
> function lost somewhere, way down the page. Sometimes it's the other
> way round, and you have a bit lambda that you're folding with, but you
> don't want the name of the list to be some anonymous bit of text a
> very long way away from the word "fold".
>
> On Wed, Nov 28, 2012 at 4:40 AM, William Smith <bills@wwayneb.com> wrote:
>> List.fold_left expects the List as the 3rd parameter with the second
>> parameter being the initial value.
>>
>> Hashtbl.fold expects the Hasthbl as the second parameter with the 3rd
>> parameter being the initial value... just the opposite of List.fold_left.
>>
>> Is there a reason for this difference?   I'm having trouble remembering
>> which goes which way.   If it's not a historical accident, I'd like to have
>> a understanding of why they are different to help me know which is which.
>>
>> Thanks,
>>
>> Bill
>>
>> --
>> Caml-list mailing list.  Subscription management and archives:
>> https://sympa.inria.fr/sympa/arc/caml-list
>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>> Bug reports: http://caml.inria.fr/bin/caml-bugs
>


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] List.fold_left vs. Hashtbl.fold
  2012-11-30 16:00     ` Gabriel Scherer
@ 2012-11-30 16:48       ` Daniel Bünzli
  0 siblings, 0 replies; 17+ messages in thread
From: Daniel Bünzli @ 2012-11-30 16:48 UTC (permalink / raw)
  To: Gabriel Scherer; +Cc: caml-list

Le vendredi, 30 novembre 2012 à 17:00, Gabriel Scherer a écrit :
> I don't know. "function application is just space" is indeed a
> convenient syntax to emulate other syntaxes (for example embed a
> concatenative language through cunning continuation-passing-style),

My concern is not really about the syntax.

> but that doesn't need to go away with non-currified functions, which
> is about applying all arguments, not necessarily forcing a tupled
> syntax.

That's the point, currying allows you to build a function incrementally with things happening between each applied argument.  

This is for example very useful to meta-program other languages from OCaml (using the abstraction mechanisms and variable binders of OCaml itself). It may not be very clear (the whole program is not here, if you are interested I can mail you the whole example), but with the combinators given at the end of this message, I'm able to gradually construct a program representing a function in another language, with an arbitrary number of arguments, compile it, and then get it as regular OCaml function (Program.as_fun) that uses OCaml gound types and that can be passed around completely hiding that the function may actually not be executed by OCaml at all.

Currying gives you glue, I'm not sure you could do these kind of things without it. If you can't then currying is not overrated to me. See also http://mlton.org/Fold

Best,

Daniel

type 'a exp (* expressions constructed with combinators *)

module Program : sig
  type 'a t  
  type ('a, 'b, 'c) stage (* b is the type of the constructed function *)

  (* Note. The types enforces that only caml functions from 'a exp(s) to
   'a exp will be accepted for compilation into a program. *)

  val retb : ('a exp -> 'b) -> ('a exp -> 'b, bool , [`Bool ]) stage
  val reti : ('a exp -> 'b) -> ('a exp -> 'b, int , [`Int ]) stage
  val retf : ('a exp -> 'b) -> ('a exp -> 'b, float, [`Float]) stage

  val argb : (bool_e -> 'a, 'b, 'c) stage -> ('a, bool -> 'b, 'c) stage  
  val argi : (int_e -> 'a, 'b, 'c) stage -> ('a, int -> 'b, 'c) stage
  val argf : (float_e -> 'a, 'b, 'c) stage -> ('a, float -> 'b, 'c) stage

  val compile : ('a exp, 'b, 'a) stage -> 'b t
  val as_fun : 'a t -> 'a
  val source : 'a t -> string
end




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] List.fold_left vs. Hashtbl.fold
  2012-11-30 10:06   ` Stefano Zacchiroli
@ 2012-11-30 16:00     ` Gabriel Scherer
  2012-11-30 16:48       ` Daniel Bünzli
  0 siblings, 1 reply; 17+ messages in thread
From: Gabriel Scherer @ 2012-11-30 16:00 UTC (permalink / raw)
  To: Stefano Zacchiroli; +Cc: caml-list

> ... but I'm curious about this "dubious" point. Is it something that has
> already been discussed in the context of OCaml and I've missed the
> relevant discussion? Or is it something there are results available
> elsewhere? Either way, pointers on that would be very much appreciated!

My personal issue with Scala syntax is that the scope of the anonymous
function is entirely implicit: if you write (li.map(_ + 1)) it will
desugar into (li.map (x => x + 1)) (apparently to the first
parenthesis level), but (if (_) foo else bar) desugars to (fun x => if
x foo bar), and ((_ : Int) + 1) to (fun x => (x : Int) + 1); there is
no explicit enclosing boundary, the scope is the "smallest expression
that contains the underscore" for some notion of "containing" that I
don't find particularly intuitive on the examples above.

I think implicit scopes are a "dubious" idea and would really want an
explicit construction to mark the scope of these doubly anonymous
functions. The problem is that you have to find a really light syntax,
as the value of this construction is precisely its concision. In my
young years I used to think that Camlp4 syntax extensions could be
beneficial, and I wrote an extension for this purpose (  :
http://bluestorm.info/camlp4/pa_holes.ml.html  ). It allows to write
for example (\ \2 \1) for the swap function: (\ ... ) delimits the
abstraction scope and variable are written \n (_ would be another
compromise: less expressive on the ordering, but shorter).

Another upside of these syntax is that they give light thunking for
free: proponents of lazy evaluation like the fact that some control
construct can be defined as simple functions under a lazy stragy,
while writing
  if b (fun () -> e1) (fun () -> e2)
is too painful to be viable in ML. Well,
  if b (\ e1) (\ e2)
(using the convenition that there is always at least one parameter) is better.

> And thanks for your efforts in fueling language design discussion on
> this list!, I really appreciate it and the resulting discussions.

It's a double-edged sword: it's easy to get lost in mundane details or
ultimately void debates about "the next programming language" on a
list that is really about OCaml users. I wasn't sure already that
discussion of Scala's implicit function syntax was in-topic, but well.
I'll try to keep my side of the discussion not too long.

Daniel Bünzli wrote:
> I have the *impression* that currying is essential when you want to devise dsls and combinators that integrate naturally in the host language. But I may be wrong.

I don't know. "function application is just space" is indeed a
convenient syntax to emulate other syntaxes (for example embed a
concatenative language through cunning continuation-passing-style),
but that doesn't need to go away with non-currified functions, which
is about applying all arguments, not necessarily forcing a tupled
syntax. Only partial application would be less convenient (but you can
still explicitly define functions-that-return-functions). That would
certainly need more experimentation.

On Fri, Nov 30, 2012 at 11:06 AM, Stefano Zacchiroli <zack@upsilon.cc> wrote:
> On Fri, Nov 30, 2012 at 10:53:21AM +0100, Gabriel Scherer wrote:
>> My personal opinion is that currying is overrated
>
> Very much agreed!
>
>> and we should think about language design without currying, and with a
>> nice short syntax for partial application (inspired by Scala's
>> admittedly dubious (foo _ bar) syntax for (fun x -> foo x bar)).
>
> ... but I'm curious about this "dubious" point. Is it something that has
> already been discussed in the context of OCaml and I've missed the
> relevant discussion? Or is it something there are results available
> elsewhere? Either way, pointers on that would be very much appreciated!
>
> And thanks for your efforts in fueling language design discussion on
> this list!, I really appreciate it and the resulting discussions.
>
> Cheers.
> --
> Stefano Zacchiroli  . . . . . . .  zack@upsilon.cc . . . . o . . . o . o
> Maître de conférences . . . . . http://upsilon.cc/zack . . . o . . . o o
> Debian Project Leader . . . . . . @zack on identi.ca . . o o o . . . o .
> « the first rule of tautology club is the first rule of tautology club »
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] List.fold_left vs. Hashtbl.fold
  2012-11-30  9:53 ` Gabriel Scherer
  2012-11-30 10:06   ` Stefano Zacchiroli
@ 2012-11-30 11:34   ` Daniel Bünzli
  1 sibling, 0 replies; 17+ messages in thread
From: Daniel Bünzli @ 2012-11-30 11:34 UTC (permalink / raw)
  To: Gabriel Scherer; +Cc: Caml-list

Le vendredi, 30 novembre 2012 à 10:53, Gabriel Scherer a écrit :
> My personal opinion is that currying is overrated and we
> should think about language design without currying, and with a nice
> short syntax for partial application

I'm not so sure about that. It is true that when I miss currying in other language it's often because I want partial application, however I have the *impression* that currying is essential when you want to devise dsls and combinators that integrate naturally in the host language. But I may be wrong.

Daniel



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] List.fold_left vs. Hashtbl.fold
  2012-11-30  9:53 ` Gabriel Scherer
@ 2012-11-30 10:06   ` Stefano Zacchiroli
  2012-11-30 16:00     ` Gabriel Scherer
  2012-11-30 11:34   ` Daniel Bünzli
  1 sibling, 1 reply; 17+ messages in thread
From: Stefano Zacchiroli @ 2012-11-30 10:06 UTC (permalink / raw)
  To: caml-list

On Fri, Nov 30, 2012 at 10:53:21AM +0100, Gabriel Scherer wrote:
> My personal opinion is that currying is overrated

Very much agreed!

> and we should think about language design without currying, and with a
> nice short syntax for partial application (inspired by Scala's
> admittedly dubious (foo _ bar) syntax for (fun x -> foo x bar)).

... but I'm curious about this "dubious" point. Is it something that has
already been discussed in the context of OCaml and I've missed the
relevant discussion? Or is it something there are results available
elsewhere? Either way, pointers on that would be very much appreciated!

And thanks for your efforts in fueling language design discussion on
this list!, I really appreciate it and the resulting discussions.

Cheers.
-- 
Stefano Zacchiroli  . . . . . . .  zack@upsilon.cc . . . . o . . . o . o
Maître de conférences . . . . . http://upsilon.cc/zack . . . o . . . o o
Debian Project Leader . . . . . . @zack on identi.ca . . o o o . . . o .
« the first rule of tautology club is the first rule of tautology club »

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Caml-list] List.fold_left vs. Hashtbl.fold
  2012-11-30  3:06 William Smith
@ 2012-11-30  9:53 ` Gabriel Scherer
  2012-11-30 10:06   ` Stefano Zacchiroli
  2012-11-30 11:34   ` Daniel Bünzli
  0 siblings, 2 replies; 17+ messages in thread
From: Gabriel Scherer @ 2012-11-30  9:53 UTC (permalink / raw)
  To: William Smith; +Cc: Caml-list

> Before I saw other people's explanations, I was thinking about how the
> parameter order fold_left is more useful for currying.

This is a correct observation. It is the reason why, in Haskell, both
foldl and foldr request the initial accumulator before the list. I
personally think it is a mistake because you break the nice property
that you're lifting a function-on-an-argument (either ('elem -> 'acc
-> 'acc) or ('acc -> 'elem -> 'acc)) to a function-on-the-list with
the exact same typing structure.

Designing for currying is a fragile thing to do in the general case
(you can be wrong on which argument happens to be the more often
delayed) and creates tensions with other surface API design choice
(such as putting the function argument last for syntactic
convenience). My personal opinion is that currying is overrated and we
should think about language design without currying, and with a nice
short syntax for partial application (inspired by Scala's admittedly
dubious (foo _ bar) syntax for (fun x -> foo x bar)). Labels also
provide a solution for this that is usable in OCaml APIs today (but I
think for the Language of the Future we could forget labels and use a
flexible notion of records to provide similar naming and
order-irrelevance) -- just remember to avoid optional arguments that
have other downsides.

On Fri, Nov 30, 2012 at 4:06 AM, William Smith <bills@emu-bark.com> wrote:
> That seems like an easy mnemonic--left means the base case argument is on
> the left and right means that the base case is on the right.   This is both
> for the parameters to fold_left/right and the parameters of its <fun>
> argument.  And then, if there is not _right/_left distinction available for
> a container, it defaults to being equivalent to _right.
>
> Before I saw other people's explanations, I was thinking about how the
> parameter order fold_left is more useful for currying.
>
> If you want to create an operator, fold_left makes it a lot easier to curry
> in its base case and then apply the operator to different lists that the
> operator is processing last.
>
> If I wanted to do that with fold_right or the other container's folds, I
> would have to write a wrapper to swap the arguments--which isn't really a
> big deal, but it's a way that fold_left is more useful that no one
> mentioned.
>
> Bill
>
>> On Wed, Nov 28, 2012 at 6:25 PM, Gabriel Scherer
>> <gabriel.scherer@gmail.com>  wrote:
>
>
>> That's for the type. Regarding the implementation, fold_left applies
>> the argument function starting from "the left" (the beginning) of the
>> list first, while fold_right begins "on the right" (at the end): for
>> some infix operator (++) :
>>   fold_left (++) init [x; y; z]     is  ((init ++ x) ++ y) ++ z
>>   fold_right (++) [x; y; z] init   is (x ++ (y ++ (z ++ init)))
>> (The evaluation "begins" in the innermost nested parentheses)
>
>
> On Wed, Nov 28, 2012 at 5:40 AM, William Smith<bills@wwayneb.com>  wrote:
>
>> Hashtbl.fold expects the Hasthbl as the second parameter with the 3rd
>> parameter being the initial value... just the opposite of List.fold_left.
>
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Caml-list] List.fold_left vs. Hashtbl.fold
@ 2012-11-30  3:06 William Smith
  2012-11-30  9:53 ` Gabriel Scherer
  0 siblings, 1 reply; 17+ messages in thread
From: William Smith @ 2012-11-30  3:06 UTC (permalink / raw)
  To: Caml-list

That seems like an easy mnemonic--left means the base case argument is on the left and right means that the base case is on the right.   This is both for the parameters to fold_left/right and the parameters of its <fun> argument.  And then, if there is not _right/_left distinction available for a container, it defaults to being equivalent to _right.

Before I saw other people's explanations, I was thinking about how the parameter order fold_left is more useful for currying.

If you want to create an operator, fold_left makes it a lot easier to curry in its base case and then apply the operator to different lists that the operator is processing last.

If I wanted to do that with fold_right or the other container's folds, I would have to write a wrapper to swap the arguments--which isn't really a big deal, but it's a way that fold_left is more useful that no one mentioned.

Bill

> On Wed, Nov 28, 2012 at 6:25 PM, Gabriel Scherer
> <gabriel.scherer@gmail.com>  wrote:

> That's for the type. Regarding the implementation, fold_left applies
> the argument function starting from "the left" (the beginning) of the
> list first, while fold_right begins "on the right" (at the end): for
> some infix operator (++) :
>   fold_left (++) init [x; y; z]     is  ((init ++ x) ++ y) ++ z
>   fold_right (++) [x; y; z] init   is (x ++ (y ++ (z ++ init)))
> (The evaluation "begins" in the innermost nested parentheses)

On Wed, Nov 28, 2012 at 5:40 AM, William Smith<bills@wwayneb.com>  wrote:

> Hashtbl.fold expects the Hasthbl as the second parameter with the 3rd
> parameter being the initial value... just the opposite of List.fold_left.

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2012-11-30 16:49 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-11-28  4:40 [Caml-list] List.fold_left vs. Hashtbl.fold William Smith
2012-11-28 16:17 ` Lukasz Stafiniak
2012-11-28 16:25   ` Malcolm Matalka
2012-11-28 16:21 ` David House
2012-11-29  1:06   ` Francois Berenger
2012-11-28 16:42 ` Oliver Bandel
2012-11-28 17:11   ` Adrien
2012-11-28 17:41     ` Virgile Prevosto
2012-11-29  0:07       ` Jacques Garrigue
     [not found] ` <CAPFanBG04BiwJuPkV80__Ondmg1N8OEg4DokiXqDReg3ycNBdA@mail.gmail.com>
2012-11-28 17:25   ` Gabriel Scherer
2012-11-28 17:37     ` Lukasz Stafiniak
2012-11-30  3:06 William Smith
2012-11-30  9:53 ` Gabriel Scherer
2012-11-30 10:06   ` Stefano Zacchiroli
2012-11-30 16:00     ` Gabriel Scherer
2012-11-30 16:48       ` Daniel Bünzli
2012-11-30 11:34   ` Daniel Bünzli

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).