laurent.orseau
2021-1-21 09:15:54

Just a thought experiment—very likely this has been discussed multiple times already: How do you feel about replacing . rest arguments in function headers and calls with a special #:rest keyword?


laurent.orseau
2021-1-21 09:16:31

That would avoid the special syntax treatment of dot notation, leaving its used to constructing quoted data


sorawee
2021-1-21 09:16:41

but what if I want to use a keyword #:rest?!?!?


sorawee
2021-1-21 09:18:07

I always hate dotted pair, but it’s so tightly integrated (at the reader level) that I don’t think it’s possible to take them out.


laurent.orseau
2021-1-21 09:18:10

Then you’re doooooomed :stuck_out_tongue:



sorawee
2021-1-21 09:19:09

Here’s a recent question on StackOverflow asking why (quasiquote (1 unquote 2)) produces '(1 . 2)


laurent.orseau
2021-1-21 09:20:09

Yeah, these can easily get tricky indeed


laurent.orseau
2021-1-21 09:20:33

But I’m okayish with it for data dsl, as it can be very useful, in particular splicing ,@


laurent.orseau
2021-1-21 09:20:50

(admittedly this is not strictly dot notation)


sorawee
2021-1-21 09:21:01

My general thought on this matter is that I like Python’s function application a lot.


sorawee
2021-1-21 09:21:17

You don’t need a special apply or keyword-apply


sorawee
2021-1-21 09:21:26

There’s only function application


sorawee
2021-1-21 09:21:31

And that suffices for everything


laurent.orseau
2021-1-21 09:21:56

I like it too


laurent.orseau
2021-1-21 09:30:03

*args and **kwargs could easily be mimicked with special keywords #:args and #:kwargs (in an even more unified interface that python’s special syntax with * and **)


laurent.orseau
2021-1-21 09:32:23

#:args or #:pos-args would be the the whole list of positional arguments, while #:rest would be the remaining ones after given positional arguments


laurent.orseau
2021-1-21 09:33:03

These can appear both in a function header and in a function call. But if giving #:args in a call, then no other positional argument should be specified—something like that.


laurent.orseau
2021-1-21 09:35:06

Of course having #:args and such in calls would require redefining #%app (at least to have good error messages)


sorawee
2021-1-21 09:36:32

What about this?


sorawee
2021-1-21 09:36:35

#lang racket (define (f a [b] [c 'c] [d 'd] #:args args #:kwargs kwargs) (list a b c d args kwargs)) (f 'a 'args0 'args1 #:b 'b #:c 'c* #:e 'kwargs0 #:f 'kwargs1) ; 'a 'b 'c* 'd '(args0 args1) (hash 'e 'kwargs0 'f 'kwargs1)


sorawee
2021-1-21 09:37:33

Doesn’t support positional optional argument. Keyword and its corresponding variable name coincide.


sorawee
2021-1-21 09:38:34

Coerce keyword to symbol in kwargs (users should not need to deal with keyword? at all… unless they write a macro that manipulates keywords)


sorawee
2021-1-21 09:39:36

I think one reason Racket’s app and function definition are the way they are is that they want to maintain symmetry between the definition site and application site


sorawee
2021-1-21 09:40:00

which I think is nice, but not terribly useful


laurent.orseau
2021-1-21 09:43:29

I was thinking something a little different, but breaking a little the symmetry.


laurent.orseau
2021-1-21 09:43:56

positional arguments don’t have names in function calls (like it is now)


sorawee
2021-1-21 09:44:56

I’m waiting to hear “de Bruijn index” from you :wink:


laurent.orseau
2021-1-21 09:45:10

let me google it again :smile:


laurent.orseau
2021-1-21 09:45:36

haha yeah, no :smile:


laurent.orseau
2021-1-21 09:45:58

By names I meant keyword names


laurent.orseau
2021-1-21 09:46:29

So (define (f a b)...) cannot be called with (f #:a 'a #:b 'b).


laurent.orseau
2021-1-21 09:48:16

#lang racket (define (f a b [c 'c] [d 'd] #:args args #:kwargs kwargs) (list a b c d args kwargs)) (f 'a 'b 'c #:d 'dd) ; (f 'a 'b 'c 'd #:args '(a b c d) #:kwargs '((d . dd))) (edit [b] -> b)


laurent.orseau
2021-1-21 09:49:39

and #lang racket (define (f a [b] [c 'c] [d 'd] #:args args #:kwargs kwargs #:rest rest) (list a b c d args kwargs rest)) (f 'a 'b 'c 'd2 'e 'f #:d 'dd) ; (f 'a 'b 'c 'd2 #:args '(a b c d2 e f) #:kwargs '((d . dd)) #:rest '(e f))


sorawee
2021-1-21 09:50:39

No kw-rest?


laurent.orseau
2021-1-21 09:50:54

yes, sounds good


laurent.orseau
2021-1-21 09:51:54

If #:kwargs is used in a call, then no other keyword argument (including #:kwrest ) can be used. Similarly to #:args


laurent.orseau
2021-1-21 09:52:54

If #:kwrest is used in a call, then the other mandatory keyword arguments must be still be provided


laurent.orseau
2021-1-21 09:54:29

The nice thing about this design is that it should be almost entirely backward compatible with Racket (except for the special keyword names) and can easily revert to Racket’s calls and definitions when the special keywords are not used


laurent.orseau
2021-1-21 09:54:59

That means it keeps Racket’s efficiency, unless you need more flexibility


laurent.orseau
2021-1-21 10:07:20

(define (f a [b 'b] #:rest r) (list a b r)) (f 'a #:rest '(x y)) ; = (f 'a 'b #:rest '(x y)) (f 'a 'x 'y) ; = (f a x #:rest '(y)) Is this sensible?


sorawee
2021-1-21 10:12:38

You want to support optional positional arg, right? If so, then yeah, this makes sense


laurent.orseau
2021-1-21 10:14:17

Yes, mostly for backward compatibility though. You got me thinking that they’re often not that great.


kellysmith12.21
2021-1-21 22:15:41

Instead of a #:rest keyword, my lang has ... after a rest argument. (I still need to implement kw... for kwargs). It was easy to translate it into apply, just a short #%app extension.


kellysmith12.21
2021-1-21 22:16:16

(On account of that, my lang doesn’t even provide apply.)


notjack
2021-1-22 03:07:46

I’m definitely a fan of using ellipses for this