Does any other language use the uniform initialization syntax found in c++? [closed]

Are there any other languages that use the new C++11 uniform initialization syntax thoroughly throughout the entire language, or is this entirely a C++ idiom at this point?

I tried googling and thinking of any off the top of my head and couldn’t really find any.

For those not familiar with C++11:

Basically, your typical initialization in C++ used to be an assignment/copy initializer similar to other languages:

int x = 5;

Now, the new syntax that is recommended for use is:

int x{5};

This is called the new uniform initialization syntax.

11

Uniform initialization syntax seems geared to aggregate types. Looking at the FAQ, UIS’s purpose is to solve a variety of loosely (or subtly?) related problems (ambiguities and impossibilities), some of which don’t exist or have other solutions in other languages. Consequently, I don’t think you’ll find anything exactly the same in other languages; you may find similar syntax, but less so the semantics.

The problems that UIS addresses include:

  1. initializing aggregate types that don’t have constructors (including arrays) outside of definition statements (such as in member initialization lists). UIS addresses this by expanding the initializer list feature (in a sense, UIS is an expansion of initializer lists), which exists in other language. Robert Harvey’s answer is one example. Initializer lists also exist in previous versions of C++ and C, going back to at least C99

  2. ambiguous declarations. The following could be a function declaration or variable definition, depending on context:

     int b(foo);
    

This isn’t a common issue in other languages.

  1. need to repeat class in constructor name, when it could be inferred from context:

     Complex c = {1,1};
     Complex conjugate(const Complex& c) {
         return {c.real(), -c.imaginary()};
     }
     Complex d = conjugate({1,1});
    

Other languages generally approach the first from another angle, using type inference:

    var c = Complex(1,1);

Other languages also use type conversion to cover some instances of the other two cases (function argument and return type inference). UIS is more general in that it supports converting a bunch of values, where most languages only support converting a single value (i.e. multiple parameter constructors can participate in conversions in C++, where usually only unary converters are supported in other languages; however, see “Implicit Conversions” under Scala for a workaround).
4. addressing the above (which add bare “{…}” expressions to C++) adds a new issue: constructor argument list delimiters aren’t consistent with UIS. Allowing constructor argument lists to use brackets instead of parentheses makes various other construction expressions consistent with implicit constructor names:

    Foo f{x};   // direct initialization
    new Foo{x}; // explicit constructor name
    z = Foo{x}; // cast
    Foo{x};     // temporary

Scala#

Scala has a similar syntax (closer to C#’s than C++’s) for instance creation expressions that covers the initializer-list use-case:

class Foo(var bar:String=null) {}
var foo = new Foo() {bar="Bar"}

However, the semantics are different. Rather than simply initializing object fields, the bracketed expression after the constructor creates a new anonymous class that’s a child of the named class, which is then instantiated. The constructor for the anonymous class includes the initializations in the brackets. The variable’s type is the anonymous class, rather than the named class.

Since a new class is defined, it can also include just about any statement allowed in a class definition, such as field and method definitions.

class Foo(var bar:String=null) {}
var foo = new Foo() {bar="Bar"; var baz="Baz", def qux()=bar+baz}

Unlike C++ and like C#, the equals symbol is required.

Something like the example definition in the question is valid in Scala, but it has different semantics from anything previously mentioned:

var i = {5}

In this case, the bracketed expression is simply a compound expression and equivalent to the following C++ statement:

int i = (5);

Implicit Conversions

Conversions in Scala are handled with views and implicit classes. When coupled with tuples, these can be used to convert multiple values to a single type without specifying the type, similar to UIS when the list contains constructor arguments and no class name is given. Like UIS, the type can be inferred from context. Unlike UIS, parentheses are used rather than brackets (as tuples are delimited with parentheses).

Note that Scala has another kind of implicit thing, the implicit parameter, which makes an appearance below in sign. Rather than being used when implicitly converting values, it’s used to implicitly provide arguments to a function (i.e. when an argument isn’t explicitly passed to a function, a value is automatically created and passed). The use of the word “implicit” for different things isn’t a naming collision; all the implicit things work together to extend behavior (more on this below).

Implicit class:

// note: sign[T](n)(num) is a curried function
def sign[T : Numeric](x:T)(implicit num:Numeric[T]) = num.compare(x, num.zero)

implicit class Complex(ri:(Double,Double)) { 
  val real = ri._1
  val imaginary = ri._2
  def conjugate = new Complex((real, -imaginary))
}
// could also be methods of Complex
def abs(c:Complex) = Math.sqrt(c.real * c.real + c.imaginary * c.imaginary) 
def sqrt(c:Complex) = {
  val real = Math.sqrt((abs(c)+c.real)/2)
  val imaginary = sign(c.imaginary) * Math.sqrt((abs(c)-c.real)/2)
  new Complex((real, imaginary))
}

val c:Complex = (1.0,2.0)
sqrt((3.0,4.0))
// Conversions can even be used for method calls, which I don't think UISs can do
(1.0,2.0).conjugate

View:

def sign[T : Numeric](n:T)(implicit num:Numeric[T]) = num.compare(n, num.zero)

class Complex(val real:Double, val imaginary:Double) {
  def conjugate = new Complex(real, -imaginary)
}
implicit def complexify(ab:(Double, Double)) = new Complex(ab._1, ab._2)

def abs(c:Complex) = Math.sqrt(c.real * c.real + c.imaginary * c.imaginary) 
def sqrt(c:Complex) = {
  val real = Math.sqrt((abs(c)+c.real)/2)
  val imaginary = sign(c.imaginary) * Math.sqrt((abs(c)-c.real)/2)
  new Complex(real, imaginary)
}

val c:Complex = (1.0,2.0)
sqrt((3.0,4.0))
(1.0,2.0).conjugate

Aside: as mentioned above, implicits in Scala are used to extend behavior. Implicit conversions for method calls ((1.0,2.0).conjugate in the examples) are usually used as an indirect way to add methods to an existing class by using the adapter pattern. Other languages (such as C#, Objective-C, Ruby and Python) take another approach and have open classes, allowing new methods to be added directly. For examples, consider C#’s extension methods, F#’s type extensions, Objective-C’s categories and Haskell’s type classes (which also addresses C++ overloading and template concepts). Scala’s implicit parameters and objects can also be used like Haskell’s type classes (instead of the adapter pattern you get with implicit conversions) basically the way you create traits classes in C++. For more on this topic:

  • Making Our Own Types and Typeclasses
  • Retroactive Supertyping in Scala: Adaptors, Rich Wrappers, Type Classes, and Structural Types
  • The Neophyte’s Guide to Scala Part 12: Type Classes
  • A Small Example of the Typeclass Pattern in Scala
  • Type Classes as Objects and Implicits (PDF)

Looking at things like sign and (1.0,2.0).conjugate, I can’t help but feel that Scala is weird and wonderful.

Erlang#

Erlang’s record initializers use squiggly brackets and key-value pairs. The record name must be given (prefixed with “#”). Fields with default values can be left out of the initializer.

-record(foo, {bar, baz="Baz"}).
Foo = #foo{bar="Bar"}.

During compilation, records are converted to tuples, losing the field names.

Go#

In Go, composite literals can be used to initialize objects. Like similar features in other languages, brackets are used as delimiters. Unlike UIS (but like other languages), the type must be included. Within the brackets is an element list. An element can itself be a composite literal. Lists can be keyed or unkeyed (keys give struct field names, array indices or map keys); keys must be present or absent for all elements in a list (this restriction doesn’t apply across separate lists within a literal). If keys are absent, all fields must be given values.

type Point3D struct { x, y, z float64 }
type Line struct { p, q Point3D }

// 3 different lists, 1 keyed and 2 unkeyed:
ln0 := Line{Point3D{x: 1}, Point3D{0,1,1}};
// array length could also be given as "...":
ns := [3]int32{0,1,2}
// strs[2] is given zero value for strings:
strs := [...]string{0:"", 1:"I", 3: "III"}

Haskell#

Haskell types can be declared with a record syntax, which are very similar to Erlang’s records. Record constructors can take a initializers. Record syntax also declares accessor functions with the same name as the fields, and record fields can be updated using the same syntax as initialization. As far as I know, default values cannot be provided for fields, so all fields must be present in the initializer (though not when updating), though they can be given in any order.

data Foo = Foo {bar::String, baz::String}
foo = Foo {baz="Baz", bar="Bar"}
bar foo # "Bar"
# update by name
qux = foo {bar="qux"}

Similar to Erlang, records are converted to plain types; the above results in:

data Foo = Foo String String
bar (Foo bar baz) = bar
baz (Foo bar baz) = baz

(except that this doesn’t support initializers or updates-by-name.)

Perl 5 & Javascript#

Perl 5 and Javascript don’t have language level support for initializer lists, but constructors can take hashes (Perl 5) or objects (Javascript), which they can use to set object fields. Coincidentally, JS object literals and Perl hash refs use squiggly brackets (though Perl doesn’t need to use hash refs to pass a hash to a constructor).

Perl 5:

package Foo;

sub new {
    my $class = shift;
    my $self = {@_};
    return bless $self, $class;
}

package main;

my $foo = new Foo(bar=>"Bar");

JS:

function Foo(obj) {
    for (var p in obj) {
        this[p] = obj[p];
    }
}
var foo = new Foo({bar: "Bar"})

Perl 6#

As with Perl 5, a hash can be passed to constructors to set attributes. Unlike Perl 5, Mu, the Perl 6 root class, has a constructor which takes a hash and defines attributes & accessors, so this doesn’t need to be explicitly implemented.

class Foo {
    has $.bar as rw;
}
my $foo = Foo.new(bar=>"Bar");

Powershell#

Powershell’s new-object command supports initialization, property addition and method invocation using the -Property argument:

New-Object PSObject -Property @{
    foo = "bar"
}

3

C# has something similar; they’re called Object/Collection Initializers. They have several, but similar, forms:

// Object initialization
var cat = new Cat { Age = 10, Name = "Fluffy" };

// Object initialization with anonymous type
var pet = new { Age = 10, Name = "Fluffy" };

// Collection initialization
var digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

// Collection initialization with Linq and anonymous type
var productInfos =
    from p in products
    select new { p.ProductName, p.UnitPrice };

Note that var in C# has the same function as auto in C++.

Also note that the form:

int x{5}

is really just the “scalar” form of a collection initializer (it is a single element, potentially belonging to some collection).

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật