Arc Forumnew | comments | leaders | submitlogin
2 points by rocketnia 4068 days ago | link | parent

"I have no idea what I was saying there"

Oh, well I got a lot from it. :) I may have quoted you out of context just now, but I think your post was the first time I thought about the idea that optional args and Haskell-like currying may encourage opposite argument orders. If a function argument is going to remain mostly constant, it should go last so it can be optional, but it should also go first so we can curry it away.

Since then, I've come to think the conundrum is largely internal to currying itself: Currying is useful when people have a frequent need to insert their own locally constant value. That's a tenuous balance in itself, and only one half of it conflicts with the general idea of putting stable values toward the end.

(Here's another really old exchange about argument order in Haskell: http://arclanguage.org/item?id=4705)

At the moment, I just say no to currying. I even manually eta-expand higher-order applications so it's easier to see what function signatures I expect, and so they're easier to step through in a debugger.

  // No:
  _.arrAll( arr, _.isString )
  
  // Yes:
  _.arrAll( arr, function ( x, i ) {  // or just ( x )
      return _.isString( x );
  } )


2 points by akkartik 4065 days ago | link

After reading http://arclanguage.org/item?id=4703, I wanted to be able to say both:

  (map f (keep f (sort > ..)))
and:

  (map :over seqs
       (fn (f) ..))
But I can't do that. The ways that wart gets in the way are instructive:

a) First I tried adding an alias to https://github.com/akkartik/wart/blob/2fa2a3b1c0/043list.war...:

  def (map f seq|over)
    ..
But it was easy to forget that I extend map later on: https://github.com/akkartik/wart/blob/2fa2a3b1c0/050list2.wa....

Lesson: when adding param aliases we need to update all later extensions. That seems painful.

b) Even after I identified both places to modify, it's unclear how to deal with this declaration:

  def (map f ... seqs)
I could make it:

  def (map f ... seqs|over)
But then this call combines all args into seqs.

  map :over fs
      (fn (f) ..)
Lesson: rest args by keyword sometimes don't work well. Better to try to find the right names for other args.

Maybe something like this?

  map fs :do (fn (f) ..)
I still can't think of the right keyword to make this readable.

Update: I ended up going with

  map fs :with (fn (f) ..)
(https://github.com/akkartik/wart/commit/537fb6d832)

I also made a change to permit keyword args after rest keyword args:

  map :over fs :with (fn (f) ..)
(https://github.com/akkartik/wart/commit/b3667cda49)

Which of these do people prefer? Any other options?

-----