

Keyword Arguments: Ruby, Clojure, Common Lisp - bgray
http://briancarper.net/blog/579/keyword-arguments-ruby-clojure-common-lisp

======
kbd
More like "how Ruby and Clojure don't really support keyword arguments".
Unless you can do something like:

    
    
        >>> def foo(a,b):
        ...   print a,b
        ... 
        >>> foo(b=1,a=2)
        2 1
    

then you don't support keyword arguments, you just have some hack for stuffing
parameters into a hash. In fact, MacRuby had to add syntax to Ruby[1] in order
to be able to represent Objective C keyword arguments.

[1] [http://www.macruby.org/documentation/rubycocoa-to-
macruby.ht...](http://www.macruby.org/documentation/rubycocoa-to-macruby.html)

~~~
cageface
I find Python inelegant in general but Python's support for keyword arguments
strikes the best balance of simplicity and flexibility in any language I've
used.

~~~
MostAwesomeDude
Python's argument conventions are even more flexible; they actually work by
passing a tuple of positional arguments and a dictionary of keyword arguments,
and unpacking/repacking according to the signature of each function. You can
pass any iterable as positional arguments and any mapping as keyword
arguments. You can also retrieve the positional and keyword arguments inside a
callable as a tuple and dictionary. It's the best calling convention I've ever
seen.

------
aerique
Isn't being able to give functions as a default keyword argument more or less
obvious when functions are first-class objects instead of it being insane?
It's something that I use several times in any decent sized project.

For my bot for the current Google AI challenge I use A* pathfinding and one of
the keyword args is the function for getting a node's neighbours.

~~~
technomancy
Yes, all these languages support that. My CL is rusty, and it's not clear from
the article, but I think he's talking about providing a function to calculate
the default value from some of the other args.

------
danking00
Ruby has a penchant for giving you more than enough rope to hang yourself on,
and "Ruby keyword arguments" are no different. I've seen them used in the
wild. It's horrendous.

The code I had to update was poorly written, but the functions with "keyword
arguments" were practically incomprehensible _because I didn't even know what
their parameters were_. Furthermore, the interactions between these "keyword
arguments" wasn't documented anywhere. Sometimes supplying one keyword
demanded that another keyword also be supplied, less the function quietly
fails.

Finally, there's no way to make a "keyword argument" a required argument.
Every function I saw with keyword arguments was littered with "bar =
foo.key?(:bar) ? foo[:bar] : default_value" or "throw Exception if not
foo.key?(:bar)"

Don't use hashes as a replacement for argument lists in Ruby. Hack the Ruby
source and add real keyword arguments.

edit: added another example

~~~
andrewvc
Well, keyword arguments can be used well in ruby, though clearly, in the code
you've been dealing with they haven't.

Some guidelines. Use .merge for default values, not ternary operators. Keep it
minimal. Rails does a good job of using keywords for stuff that's optional,
and positional arguments for stuff that isn't. For instance

    
    
        link_to 'My Website', 'http://example.net', :class => 'my-css-class'.
    

Here, the arguments you need, the link title and href are non-optional
positional args. HTML attributes OTOH are option hash args..

It sounds like in the code you've inherited, though I can't be sure, there are
fairly complicated hashes being passed around all kinds of places. These
should probably be objects, not hashes, in the first place. I'll admit though,
I can't be certain from my limited vantage point.

~~~
danking00
I think the hashes instead of objects paradigm contributed to my frustration.

I ended up turning parts of the hashes into objects and parts into parameters.

You and your sibling post provide some decent guidelines and approaches to
default arguments. My experience with Ruby has lead me to believe that it's an
awesome language, but a language which I'd be very careful about with whom I
collaborated.

------
andrewflnr
He spends a lot of time on the syntactic ambiguities of keyword arguments in
Ruby when calling without parens. I understand how that's annoying, but how
hard would it be to just put the parentheses back? He seems to be making a
mountain of a molehill on that point.

~~~
sanderjd
Seriously. I can't think of any language feature in any other language that is
heaped with so much passion (both positive and negative), while being entirely
mundane.

~~~
xentronium
Optional parens are _great_ for building DSLs and bad for everything else.

As a rule of a thumb, I don't omit parens outside macros like `before_filter
:smth` or `validates_presence_of :smth` or RSpec DSL `it "should ..." do`.

------
masklinn
A 2000 words article on keyword arguments which fails to mention any of
Python, Objective-C and Smalltalk?

~~~
xyzzyz
I suppose this is an article about keyword arguments _in Ruby, Clojure and
Common Lisp_.

------
richcollins
I've never found a situation where keyword arguments are a better choice than
setters. Setters are dynamic, you can override their implementation. Keyword
args only let you override the method that receives them, which provides less
granularity and leads to duplication (assuming there is more than one method
that accepts a shared arg).

~~~
Zak
_I've never found a situation where keyword arguments are a better choice than
setters._

When you're programming in a functional style, perhaps? The idea of a setter
doesn't make much sense in Clojure where the native data structures are
immutable, implementation inheritance is strongly discouraged and state
changes require a little more work than "x = y".

------
rawsyntax
quote: Positional arguments require mentally lining up the 7th argument in
your function call with the 7th argument in the function signature, and so on.

If your function has 7 arguments, consider refactoring

~~~
masklinn
If your refactoring is to make a 7-args function into a builder object
(because what you're building actually _needs_ those arguments), you're better
off with keyword arguments.

