List Comprehensions to Increase Productivity

August 18, 2023 by
Kaleigh Downing

One of the key advantages of Inmanta is the ability to significantly increase the productivity of our customers in rapidly creating new orchestration models. This empowers them to swiftly automate and release new services and features. Our purpose-built modeling language, Inmanta DSL, enhances productivity and usability, and we continuously strive to improve it.

Inmanta DSL now supports list comprehensions with filter support, allowing for more concise and efficient models without the need for Python plugins. This brings several benefits, such as speeding up development, improving model readability, and slightly enhancing performance. In particular, for tree-like models commonly found in YANG or REST-based adapters, the use of list comprehensions significantly impacts the modeling style. 

Model example for list comprehensions

Let’s illustrate this with a model example from our SR Linux example project. Suppose we want to go one step further by making an abstraction of the modeling of OSPF. In Inmanta DSL, you can easily make such an abstraction by adding an implementation. With the previous version of our compiler, this implementation might start as follows (note the use of constructor trees as described in the previous blog post):

implementation device_ospf for Router:
    network_instance = srlinux::NetworkInstance(
        device=self.device,
        name="default",
        protocols=srnetinstance::Protocols(
            ospf=srprotocols::Ospf(
                instance=srospf::Instance(
                    name="1",
                    router_id=self.ospf_router_ip,
                    admin_state="enable",
                    version="ospf-v2",
                    area=srospfinstance::Area(
                        area_id="0.0.0.0",
                    ),
                )
            )
        ),
    )
end

Now, there is one thing still missing: for each of the router’s interfaces, we need the network_instance.interface relation, as well as add the interface to the srospfinstance::Area instance. Considering that we need to loop over self.interfaces, this means a for loop, and we have to give the Area instance a name so we can refer to it:

implementation device_ospf for Router:
    network_instance = srlinux::NetworkInstance(
        device=self.device,
        name="default",
        protocols=srnetinstance::Protocols(
            ospf=srprotocols::Ospf(
                instance=srospf::Instance(
                    name="1",
                    router_id=self.ospf_router_ip,
                    admin_state="enable",
                    version="ospf-v2",
                    area=area,
                )
            )
        ),
    )

    area = srospfinstance::Area(
        area_id="0.0.0.0",
        parent_instance=network_instance,
    )

    for interface in self.interfaces:
        interface_name = "{{ interface.name }}.0"
        network_instance.interface += srnetinstance::Interface(
            name=interface_name
        )
        area.interface += srospfarea::Interface(
            interface_name=interface_name
        )
    end
end

This is quite cumbersome, and we partially lose the ability to use constructor trees. Now, we can use list comprehensions to help us write this implementation more elegantly:

implementation device_ospf for Router:
    interface_names = ["{{ interface.name }}.0" for interface in self.interfaces]

    network_instance = srlinux::NetworkInstance(
        device=self.device,
        name="default",
        interface=[
            srospfarea::Interface(interface_name=name)
            for name in interface_names
        ],
        protocols=srnetinstance::Protocols(
            ospf=srprotocols::Ospf(
                instance=srospf::Instance(
                    name="1",
                    router_id=self.ospf_router_ip,
                    admin_state="enable",
                    version="ospf-v2",
                    area=srospfinstance::Area(
                        area_id="0.0.0.0",
                        interface=[
                            srospfarea::Interface(interface_name=name)
                            for name in interface_names
                        ],
                    ),
                )
            )
        ),
    )
end

The introduction of list comprehensions in our language marks a significant improvement in productivity and usability. It allows developers to write more concise and intuitive code. This enhancement is part of an ongoing effort to make the language more user-friendly and effective. We encourage developers to explore and leverage the power of list comprehensions in their projects to enhance development speed, model readability, and overall efficiency.  

Kaleigh Downing August 18, 2023
Share this post
Tags