Well, it depends if you're talking vanilla Arc, or a different implementation.
If you want to go with base Arc, you can pass a dictionary in, something like this:
(def greet ((o arg-dict (obj)))
(prn "Hello there, "
(or arg-dict!person "friend")
"! Would you like "
(or arg-dict!thing-to-offer "some ice cream")
"?"))
arc> (greet)
Hello there, friend! Would you like some ice cream?
"Hello there, "
arc> (greet (obj person "Darth Vader" thing-to-offer "a lightsaber"))
Hello there, Darth Vader! Would you like a lightsaber?
"Hello there, "
arc> (greet (obj thing-to-offer "two lightsabers"))
Hello there, friend! Would you like two lightsabers?
"Hello there, "
arc>
You could, I suppose, treat a rest argument as a list of (keyword argument) pairs:
(def greet2 arg-list
(let args (pair arg-list)
(prn "Hello there, "
(or (alref args 'person) "friend")
"! Would you like "
(or (alref args 'thing-to-offer) "some ice cream")
"?")))
arc> (greet2)
Hello there, friend! Would you like some ice cream?
"Hello there, "
arc> (greet2 'person "Darth Vader" 'thing-to-offer "a lightsaber")
Hello there, Darth Vader! Would you like a lightsaber?
"Hello there, "
arc> (greet2 'thing-to-offer "two lightsabers")
Hello there, friend! Would you like two lightsabers?
"Hello there, "
arc>
Note: this has no error checking, but the failure mode isn't awful:
arc> (greet2 'person)
Hello there, friend! Would you like some ice cream?
"Hello there, "
arc>
You can mix this with required parameters:
(def greet3 (emotion . arg-list)
(let args (pair arg-list)
(prn "Hello there, "
(or (alref args 'person) "friend")
"! I'm "
emotion
" to see you. Would you like "
(or (alref args 'thing-to-offer) "some ice cream")
"?")))
arc> (greet3 'happy)
Hello there, friend! I'm happy to see you. Would you like some ice cream?
"Hello there, "
arc> (greet3 'enraged 'thing-to-offer "to be murdered")
Hello there, friend! I'm enraged to see you. Would you like to be murdered?
"Hello there, "
arc>
I haven't used these; I've merely come up with them on the spot. No doubt other people have come up with better ideas.
Downsides include not having a good way to set defaults -- you have to supply the default each time in the code you use it. Alternately, you can put the body in a function that requires each argument, then in the "regular" function, supply the default as an argument to the helper:
(def greet4 (emotion . arg-list)
(let args (pair arg-list)
(greet4-helper emotion
(or (alref args 'person)
"friend")
(or (alref args 'thing-to-offer)
"some ice cream"))))
(def greet4-helper (emotion person thing-to-offer)
(prn "Hello there, "
person
"! I'm "
emotion
" to see you. Would you like "
thing-to-offer
"?"))
arc> (greet4 'bored)
Hello there, friend! I'm bored to see you. Would you like some ice cream?
"Hello there, "
arc> (greet4 'bored 'thing-to-offer "to go away")
Hello there, friend! I'm bored to see you. Would you like to go away?
"Hello there, "
arc>
Note that you can't explicitly pass nil this way:
arc> (greet4 'bored 'thing-to-offer nil)
Hello there, friend! I'm bored to see you. Would you like some ice cream?
"Hello there, "
arc>
Arc/Nu used to have keyword arguments, but they were a pain in the butt to implement, and only a single function actually used them, so I took them out.
So, it's possible, yes, but not easy. At least, not easy using Racket's keyword arguments. It might be easier if I did everything from scratch...