[Libguestfs] IRC question about ?foo etc

Richard W.M. Jones rjones at redhat.com
Sun Jan 8 23:13:42 UTC 2017


14:50 < cbosdonnat> pino|work, do you know how I could get ?tar passed from one function to the other in the checksum code?
14:51 < pino|work> cbosdonnat: pass it as it is, ie ?foo
14:52 < cbosdonnat> pino|work, indeed, works better... I didn't know I could use the ? in the calling function and I used the ~ instead
14:53 < pino|work> ? is handled like an option type

This is a bit complicated, but I think it may be more obvious if
you know there are two distinct issues:


Issue 1: When calling a function, ?foo is short for ?foo:foo and
         ~bar is short for ~bar:bar

If you're calling a function that takes a labelled parameter ~bar
and you want to pass (eg) a string you can do:

  func ~bar:"hello"

If you want to pass a variable [really: a binding] to the function, then:

  let v = "hello" in
  func ~bar:v

But as a special case, if the variable is called bar already, then
this works:

  let bar = "hello" in
  func ~bar

because ~bar is short for ~bar:bar (and the same for optional
parameters like ?foo).

This leads naturally to code that looks like:

  let other_func ~foo ~bar ?baz =
    func ~foo ~bar ?baz


Issue 2: Optional arguments are implemented as option types (eg. None,
         Some foo), except when defaults are used

If a function is defined as:

  let func ?foo ~bar () =
    ...

then bar is passed as an ordinary parameter, it's just that at compile
time it is given a label (the labels disappear completely at runtime).
So there is no overhead or difference for the ~bar parameter.

However ?foo is implemented as an option.  If the function is called
this way:

  func ~bar ()

then what actually happens is the first parameter is passed as None,
and foo is assigned to None inside the function.  If it is called this
way:

  func ~foo:"hello" ~bar ()

then Some "hello" is passed to the function and assigned to foo inside
the function.  [And as you can see, the syntax is confusingly
inconsistent as well, welcome to OCaml.]

This works slightly differently if the optional parameter has a
default, eg:

  let func ?(foo = "hello") ~bar () =
    ...

In this case, the implementation still passes an option (None or Some ..)
to the function (because the function still needs to have a way to
know if it was called with or without the ?foo parameter), but the
implementation also implicitly adds the following code to the
beginning of the function:

  let func ?(foo = "hello") ~bar () =
    let foo = match [real ?foo param] with None -> "hello" | Some x -> x in
    ...

so foo inside the function is not an option type in this case.


HTH,

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-top is 'top' for virtual machines.  Tiny program with many
powerful monitoring features, net stats, disk stats, logging, etc.
http://people.redhat.com/~rjones/virt-top




More information about the Libguestfs mailing list