Home > Mobile >  Make functional programming syntax in c with operator overload
Make functional programming syntax in c with operator overload

Time:12-15

#include <MySyntax.hpp>
...

//let name1 = object;
//
//let name2 = object[ othervar1 , othervar2 , values val1, val2, val3... ];


let o3 = object [ values 1, "2", true, -3.14 ]; 
std::cout << o3; // prints: object [ “0”:1 , “1”:“2” , “2”:true , “3”:-3.14 ]

I'm looking to make this in <MySyntax.hpp> with c 11. I am thinking of let being a superclass of object to achieve the initialization (just my first thought). Also operator overload the [] and << on object. But where i have no idea is the value part. In case it's not clear, anything to the right of value is put in a collection, with string number indexing (std::Map maybe?). Values can be of ANY type( Also no idea on this, templates come to mind tho). Any discussion , link's to resources , tips anything. Just looking to learn the amazing extensibility of C !

EDIT:: The key word value is required. Object will also be able to take this kind of values *see code block example again. Didn't include this at the start because it isn't my original question. I only added it to emphasize the use of values.

CodePudding user response:

You can use std::tuple to store various types and print it by overloading operator<<, and support this syntax by overloading C 23 multidimensional subscript operator.

Something like this:

#include<tuple>
#include<iostream>

template<class... Args>
using let = std::tuple<Args...>;

struct {
  template<class... Args>
  constexpr auto operator[](Args&&... args) const {
    return std::tuple(std::forward<Args>(args)...);
  }
} object;

template<class... Args>
auto& operator<<(std::ostream& os, const std::tuple<Args...>& t) {
  return std::apply([&os, i = 0](auto& first, auto&... rest) mutable -> auto& {
    os << std::boolalpha << "[" << i   << ":" << first;
    ((os << ", " << i   << ":" << rest), ...);
    return os << "]";
  }, t);
}

int main() {
  let o = object[1, "2", true, -3.14];
  std::cout << o;
}

Demo.

CodePudding user response:

I think you are better of sticking to what the standard library already offers.

  • you will be reusing tested code
  • other people will find your code easier to read.
  • no need to let C look like python, javascript (or any other language) since languages have totally different philosophies anyway.

Your object can be represented by std::tuple and then code would become this :

#include <iostream>
#include <string_view>
#include <tuple>

//-------------------------------------------------------------------------------------------------
// MySyntax.hpp

// helper function to put a heteroganous list of types into one datastructure
template<typename... args_t>
auto object(args_t&&... args)
{
    std::tuple<args_t...> obj{ std::forward<args_t>(args)... };
    return obj;
}

// convert function for pretty printing
// normally convert to output type does nothing
template<typename type_t>
const type_t& convert(const type_t& value)
{
    return value;
}

// booleans should be outputed as text
std::string_view convert(const bool value)
{
    return value ? "true" : "false";
}

// output a tuple to stream
template<class type_t, size_t... index>
void output(std::ostream& os, const type_t& object, std::index_sequence<index...>)
{
    os << "[";
    // fold expression (so there is no need to create a recursive template function)
    (..., (os << (index == 0 ? "" : ", ") << "\"" << index << "\":" << convert(std::get<index>(object))));
    os << "]\n";
}

// overload stream operator for tuples
template<typename... args_t>
std::ostream& operator<<(std::ostream& os, const std::tuple<args_t...>& object)
{
    output(os, object, std::make_index_sequence<sizeof...(args_t)>());
    return os;
}

//-------------------------------------------------------------------------------------------------
// #include <MySyntax.hpp>


int main()
{
    // use auto instead of let
   auto o3 = object(1, 2.0, true, "hello");
   std::cout << "object " << o3;

   return 0;
}
  • Related