Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make stream be a subtype of object #434

Closed
jclark opened this issue Feb 26, 2020 · 10 comments
Closed

Make stream be a subtype of object #434

jclark opened this issue Feb 26, 2020 · 10 comments
Assignees
Labels
design/incomplete Part of design not yet worked out enhancement Enhancement to language design incompatible Resolving issue may not be backwards compatible lang Relates to the Ballerina language specification status/discuss Needs discussion outside github comments status/pending Design is agreed and waiting to be added

Comments

@jclark
Copy link
Collaborator

jclark commented Feb 26, 2020

Another approach would be to define stream<T,E> as a predeclared, built-in name for an object type declared in lang.object using a variant of @typeParam. With this approach, new would be used to construct streams as normal with objects.

type Foo object {
    public function next() returns record {| xml value; |}|error? {
      ...
    }
}; 

function main() {
    Foo foo = new();
        var x = new stream<xml,error>(foo);
    // or
    stream<xml,error> x = new(foo);
}

lang.object would then include something along the lines of:

# Like @typeParam but scope is object type definition rather than function definition
# default for scope is "function"
@typeParam { scope: "object" }
type ErrorType error;

@typeParam { scope: "object" }
type ItemType any|error;

// This is for map and is method-scoped
@typeParam
type Type1 any|error;

type EmptyIterator object {
  public function next() returns () {
     return ();
  };
};

// This should probably not be public, i.e. users should stream<T,E>
// The binding from stream<T,E> to object:Stream is in the spec
type Stream object {
    private abstract object {
       public function next() returns record {| ItemType value; |}|ErrorType?;
    } impl;
    public function __init(abstract object { public function next() returns record {| ItemType value; |}|ErrorType?; } impl
                           = new EmptyIterator) {
       self.impl = impl;
    }
    public function __iterator() returns abstract object { public function next() returns record {| ItemType value; |}|ErrorType?; } {
       final var impl = self.impl;
       return new (object {
         public function next() returns record {| ItemType value; |}|ErrorType? {
	    return impl.next();
	 }
       });
    }
    public function next() returns record {| ItemType value; |}|ErrorType? {
      return self.impl.next();
    }
    public function 'map(function(ItemType val) returns Type1 func) returns stream<Type1,ErrorType> = external;
};

Phew!

Originally posted by @jclark in #406 (comment)

@jclark jclark self-assigned this Feb 26, 2020
@jclark jclark added this to the 2020R2 milestone Feb 26, 2020
@jclark jclark added enhancement Enhancement to language design lang Relates to the Ballerina language specification incompatible Resolving issue may not be backwards compatible labels Feb 26, 2020
@sameerajayasoma
Copy link
Contributor

Can we also bind from stream<T> to object:Stream?

// This is the parameter type of the object:Stream object’s __init method. 
type StreamInitFuncParamType abstract object { 
                           public function next() returns record {| ItemType value; |}|ErrorType?; 
                     } | 
                     abstract object { 
                           public function next() returns record {| ItemType value; |}|ErrorType?; 
                           public function close() ErrorType?;
                    }
;  

@jclark
Copy link
Collaborator Author

jclark commented Feb 29, 2020

stream<T> is the same as stream<T,never>. @sameerajayasoma Does that answer your question?

@jclark jclark modified the milestones: 2020R3, 2020R2 Apr 24, 2020
@jclark
Copy link
Collaborator Author

jclark commented Apr 24, 2020

Note that #457 also extends @typeparam

@jclark
Copy link
Collaborator Author

jclark commented Jul 10, 2020

Also relates to #557.

@jclark
Copy link
Collaborator Author

jclark commented Aug 15, 2020

The @typeParam extension would benefit from #447.

@jclark jclark added the status/pending Design is agreed and waiting to be added label Sep 27, 2020
@jclark jclark removed this from the Swan Lake September preview milestone Sep 27, 2020
@jclark jclark added this to the Swan Lake October preview milestone Sep 27, 2020
@jclark
Copy link
Collaborator Author

jclark commented Oct 1, 2020

We need something like @typeParam { scope: "object" } also for #615.

@hasithaa
Copy link
Contributor

The typeParam support will not work with the map method in the proposal, Because we can't statically calculate the map method signature using stream<ItemType ,ErrorType>. This requires generic support.  This affects methods like map, filter, reduce, etc. 

One possible solution is to move such methods to a lang lib module; lang.object or lang.stream.Then we can support the same use case using typeParam support. I prefer to use lang.steam for this because streams objects have special semantics as a type. That also means the stream has to be a distinct object as well.  

@jclark
Copy link
Collaborator Author

jclark commented Oct 14, 2020

I haven't thought this through yet, but I wonder whether it will be simpler to keep stream as its own basic type, i.e. we postpone this change until we have generics.

@jclark
Copy link
Collaborator Author

jclark commented Oct 15, 2020

With the original proposal in this issue, it is still the case that stream has special language support: the language knows to map stream<T,E> onto the generic type defined in lang.object using the extended @typeparam.

So I think it's a viable approach to introduce a lang.stream module to contain this definition (instead of lang.object) and also to contain definitions of functions on streams such as map and reduce. This would require extending the semantics of method call to look up the method in lang.stream when the value is a stream object, and this makes more sense if stream is a distinct object type.

This approach will also scale if we want to introduce other types like stream e.g. for event streams #440.

But it's still not clear to me whether this is better than keeping stream as its own basic type as now.

@jclark jclark added the status/discuss Needs discussion outside github comments label Oct 15, 2020
@jclark
Copy link
Collaborator Author

jclark commented Oct 16, 2020

Conclusion was not to do this for Swan Lake and wait till we have generics.

@jclark jclark closed this as completed Oct 16, 2020
@jclark jclark removed this from the Swan Lake November preview milestone Oct 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
design/incomplete Part of design not yet worked out enhancement Enhancement to language design incompatible Resolving issue may not be backwards compatible lang Relates to the Ballerina language specification status/discuss Needs discussion outside github comments status/pending Design is agreed and waiting to be added
Projects
None yet
Development

No branches or pull requests

3 participants