pyret-lang icon indicating copy to clipboard operation
pyret-lang copied to clipboard

argument order for function on list method fold() and function list.fold take params in different order

Open dbp opened this issue 11 years ago • 17 comments

dbp avatar May 30 '13 18:05 dbp

At the moment, the only use of foldl in the codebase that might notice this are in my just-revised version of sort-by and in the docs (in labelled-tree.arr and moorings.markdown); all other places are symmetric in the two arguments (e.g. folding the function _ + _). There's a use of foldr in the boids example and some private cs19 examples. This could be a pretty easy fix to push through. Does anyone object?

blerner avatar Nov 05 '13 23:11 blerner

Student code might object. Don't make this switch yet.

On Tue, Nov 5, 2013 at 6:30 PM, Ben Lerner [email protected] wrote:

At the moment, the only use of foldl in the codebase that might notice this are in my just-revised version of sort-by and in the docs (in labelled-tree.arr and moorings.markdown); all other places are symmetric in the two arguments (e.g. folding the function _ + _). There's a use of foldr in the boids example and some private cs19 examples. This could be a pretty easy fix to push through. Does anyone object?

— Reply to this email directly or view it on GitHubhttps://github.com/brownplt/pyret-lang/issues/7#issuecomment-27824458 .

jpolitz avatar Nov 05 '13 23:11 jpolitz

Today I just found that I could do:

[list: 1, 2, 3, 4].foldl(insert-heap, empty-heap)

but not

fold(insert-heap, empty-heap, [list: 1, 2, 3, 4])

because of this issue.

sorawee avatar Nov 10 '15 20:11 sorawee

Keep open?

schanzer avatar Jun 09 '17 21:06 schanzer

If we agree to consolidate the signatures, what is the collective opinion on what we want foldl(f, b, [list: x1, x2, x3]) to be?

f(x3, f(x2, f(x1, b))) or f(f(f(b, x1), x2), x3)?

There seems to be room for reasonable people to disagree. Racket prefers the former, Haskell the latter. Pyret is schizo, using the Racket style for the method, and the Haskell style for the standalone function, which is of course confusing, as @sorawee points out. (BTW, I had to write my own versions of fold[lr] when translating Patch to Pyret, but that was because of a third wrinkle that Pyret avoids on principle, viz., Patch's fold[lr] are required to be variadic.)

Racket and Haskell seem to agree on foldr.

foldr(f, b, [list: x1, x2, x3]) is

f(x1, f(x2, f(x3, b)))

But Pyret goes along only for the method, choosing

f(f(f(b, x3), x2), x1)

for the standalone, which is neither Racket nor Haskell. I think this choice is totally unique to Pyret, and is very tough to justify.

ds26gte avatar Jun 09 '17 22:06 ds26gte

Iirc, that standalone signature is compatible with for loop syntax: for foldl(acc from initial, x from xs): ... end

On Jun 9, 2017 3:35 PM, "ds26gte" [email protected] wrote:

If we agree to consolidate the signatures, what is the collective opinion on what we want foldl(f, b, [list: x1, x2, x3]) to be?

f(x3, f(x2, f(x1, b))) or f(f(f(b, x1), x2), x3)?

There seems to be room for reasonable people to disagree. Racket prefers the former, Haskell the latter. Pyret is schizo, using the Racket style for the method, and the Haskell style for the standalone function, which is of course confusing, as @sorawee https://github.com/sorawee points out. (BTW, I had to write my own versions of fold[lr] when translating Patch to Pyret, but that was because of a third wrinkle that Pyret avoids on principle, viz., Patch's fold[lr] are required to be variadic.)

Racket and Haskell seem to agree on foldr.

foldr(f, b, [list: x1, x2, x3]) is

f(x1, f(x2, f(x3, b)))

But Pyret goes along only for the method, choosing

f(f(f(b, x3), x2), x1)

for the standalone, which is neither Racket nor Haskell. I think this choice is totally unique to Pyret, and is very tough to justify.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/brownplt/pyret-lang/issues/7#issuecomment-307515411, or mute the thread https://github.com/notifications/unsubscribe-auth/AA4DwIejIp4h-TuNGQPpLvqiXIvQxioAks5sCciogaJpZM4AsiWD .

blerner avatar Jun 09 '17 23:06 blerner

Making sure for syntax works out right is critical. Having other things then line up behind it where possible is wise.

shriram avatar Jun 10 '17 17:06 shriram

l = [list: 1,2,3,4,5]
fun add(sum, n): sum + n end

# function form
fold(add, 0, l)

# method form
l.foldl(add, 0)

It looks like both the function and method forms call their args in the same order now- is this issue closeable?

Emmay avatar Dec 18 '17 17:12 Emmay

That's not a good example function, because addition has two arguments of the same type, and addition is commutative on numbers. Try

l = [list: "1", "2", "3", "4", "5"]
fun add(sum, n): sum + n end

# function form
fold(add, "", l)

# method form
l.foldl(add, "")

instead, and it gives different answers.

blerner avatar Dec 18 '17 17:12 blerner

(I'm about to type this very example!)

sorawee avatar Dec 18 '17 17:12 sorawee

You're right, @blerner , we should use foldr here to preserve the same semantics.

However, this issue is about standardizing the contracts for function and method forms. @Emmay is pointing out that they seem to be in sync now, when they were NOT in November 2015 (as per @sorawee 's comment).

schanzer avatar Dec 18 '17 17:12 schanzer

No, they're not. The method form takes a callback that takes its accumulator first; the function form takes a callback that takes its accumulator second. This appears to be a bug in the implementation of raw_list_fold in the runtime, and @jpolitz and I should fix it.

blerner avatar Dec 18 '17 17:12 blerner

(This is not about using foldl versus foldr -- lists.arr defines fold = foldl, so we expect this to be left-folding behavior. The fact that the runtime function doesn't match that is the actual bug.)

blerner avatar Dec 18 '17 17:12 blerner

Thanks, that's a helpful explanation!

Emmay avatar Dec 18 '17 17:12 Emmay

My students are reporting this as well. Any updates?

Eugleo avatar Nov 25 '20 09:11 Eugleo

I think that (and this was likely true even in 2017), we're going to be reluctant to change this on these lists since enough code is already out there that we don't want to break. It's just such a headache when someone's course background code breaks because we make a signature change, and we don't have a great mechanism for updating the signatures on some programs and not others on code.pyret.org ( http://code.pyret.org/ ).

I think a more likely way forward would be to come up with some new names for consistent versions of these methods, like fold-left and fold-right, all of which match fold, and deprecate these (removing them from documentation). That I wouldn't have much objection to doing soon if others are OK with it. There's some discussion about doing this anyway ( https://github.com/brownplt/pyret-lang/issues/353 ).

On Wed, Nov 25, 2020 at 1:55 AM, Evžen Wybitul < [email protected] > wrote:

My students are reporting this as well. Any updates?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub ( https://github.com/brownplt/pyret-lang/issues/7#issuecomment-733599780 ) , or unsubscribe ( https://github.com/notifications/unsubscribe-auth/AAA5IU56PF4LI747UPWVSN3SRTIBPANCNFSM4AFSEWBQ ).

jpolitz avatar Nov 25 '20 17:11 jpolitz

Thanks for the quick answer. I understand, I was expecting this. Bot nonetheless, I had to ask.

Eugleo avatar Nov 25 '20 18:11 Eugleo