Monday, September 26, 2011

infix "#": Eiffel's printf

It's really nice to be able to write in Liberty/SmartEiffel:

("i:=#(1), j=i+1=#(2)%N"# (&i) # (&j) ).print_on(std_output)
("obviously foo := #(2), bar := #(1)%N" # &42 # &17).print_on(std_output)

which may look cryptic to most Eiffel programmers, but may look familiar when translated into C:
printf("i:=%d, j=i+1=%d\n", i,j)
printf("obviously foo := %d, bar := %d\n", 17,42)
Beside looking a little more convoluted it actually has quite a few advantages:
  • like QString::arg of Qt fame it allows positional arguments,
  • it does not rely on variable argument function calls,
  • it does not allocate an unnecessary array to hold the arguments; each call to # actually return a ROPE which does is an ABSTRACT_STRING holding references to two substrings; the prefix "&" operator returns a LAZY_STRING (praises to Adrian for good idea) which will not be converted to a string until it gets iterated over, usually printing or copying it.
  • it allows to write things like:
    local s,t,u: STRING
    s := "Eiffel"; t:= "beautiful"
    u := s | " is a " |t| " language"
    assert (u.is_equal("Eiffel is a beautiful language")
    t.prepend("really ")
    assert (u.is_equal("Eiffel is a really beautiful language")
    -- which may also obtained with
    u := "#(1) is a #(2) language" # s # t
  • it does retain type-safety (AFAIK)

1 comment:

  1. Note: infix "&" (aka `lazy_out') is just a thin layer above "agent out" :-)

    So one only need to correctly redefine `out' (or usually `out_in_tagged_out_memory') for their objects to be nicely displayed.