Skip to content
This repository has been archived by the owner on Jun 29, 2022. It is now read-only.

Schemas: drop kind from advanced layout definition #158

Open
mikeal opened this issue Aug 8, 2019 · 6 comments
Open

Schemas: drop kind from advanced layout definition #158

mikeal opened this issue Aug 8, 2019 · 6 comments

Comments

@mikeal
Copy link
Contributor

mikeal commented Aug 8, 2019

Logging this so that I don’t forget about it.

Chatting with @warpfork today and, since you already have to use syntax when using an advanced layout to define a type that specifies to the kind it is presenting itself as the kind syntax in the advanced layout definition is redundant.

Examples:

advanced FancyMap {
  kind map
}
advanced FancyBytes {
  kind bytes
}

type FancyMapType {String:String}<FancyMap>
type FancyByteType bytes<FancyBytes>
@warpfork
Copy link
Contributor

warpfork commented Aug 9, 2019

nod.

At some point I was holding the theory (think: "loosely held") that kind statements local to each use might be useful for sanity checking and good error messages. It is definitely redundant though.

@warpfork
Copy link
Contributor

warpfork commented Aug 9, 2019

The kind of error reporting case I'm think of is exemplified by:

advanced FancySomething {
    # ...
}

type FancyMapType {String:String}<FancySomething> # one of these two is wrong
type FancyByteType bytes<FancySomething> # which one is it

What should the error message text be in such a case?

Do we have to actually load the advanced layout code in order to tell what it does? I'd much rather be able to verify the sanity of the schema with local parse of the schema alone.

Or do we emit an error message that just says

Error: FancyMapType and FancyByteType both use the advanced layout "FancySomething", but are map and bytes kind respectively

... without being able to provide the user much of a hint which one is the one to adjust?

Or do we actually have advanced layouts where we'll plug in the logic and it'll specialize itself to whatever kind we actually use it with? This one is a bit of a stretch for my imagination. (And even if we could do it, I'd still want to weigh whether it's a 'should', because istm the heft of the above questions still applies anyway. It's possible we'd want to take even reusable advanced layout logic and bundle it in a quick declaration block that's explicit about how it's supposed to be used, so we can offer that much clearer of errors if it doesn't comply.)

It's possible all this is an edge case that's not worth weighting too heavily either. Just something to think about.

@vmx
Copy link
Member

vmx commented Aug 9, 2019

Or do we actually have advanced layouts where we'll plug in the logic and it'll specialize itself to whatever kind we actually use it with?

Do I recall correctly that advanced layout implement all methods of a certain kind, but may also define more? Then one Advanced Layout could certainly (theoretically, I can't think of a good example) implement several kinds.

Which means, that I agree that we should remove that kind keyword from the Advanced Layout definition.

@rvagg
Copy link
Member

rvagg commented Aug 12, 2019

I was talking about the multiple-implementation thing on IRC while playing with the Go version of the HashMap. It can implement the methods of a List as well if we treat it as an unordered set. That's going to be one of the uses of it in Filecoin so maybe we should allow it to be first class so you can switch between the uses. A HashMap with null / nil values working as a HashSet.
But then again, maybe that's a mode you describe in the advanced layout descriptor somewhere, "this thing behaves in this way, don't expect meaningful values"?

@warpfork
Copy link
Contributor

Thumbs up to both halves of that.

maybe that's a mode you describe in the advanced layout descriptor somewhere, "this thing behaves in this way, don't expect meaningful values"?

This is where my thoughts keep wandering towards as well. Having an explicit mode will let us generate much better error messages when things are misused or composed invalidly.

This wouldn't conflict with being able to use the same implementation twice; it would just be done with two declarations, one for signalling each mode, and both referencing the same implementation.

@rvagg
Copy link
Member

rvagg commented Aug 28, 2019

Moving back to schema parsing and I found some old schema proposals in my codebase that point toward this. And, in light of #180 .. maybe I want my advanced layouts to be more flexible, even if the data model doesn't allow it

If I do:

advanced HashMap {
  kind map
  rootType HashMapRoot
}

# ... rest of HashMap schema

Then I seem to be locked into the data model. What if I did:

advanced HashMap {
  rootType HashMapRoot
}

# ... then referencing it for use in another schema as:

type BytesHashMap map { Bytes : Value } representation HashMap
type StringHashMap map { String : Value } representation HashMap

# where Value is a union type for any kind and Bytes and String are allowed
# by schema for Keys as per PR 180

One question raised in #180 was the ability to have different types in the same map, but this would act like a generic and say that it can only have Bytes or only Strings. Codegen becomes more complicated but not impossible and could be used to create things you could interact with directly outside of data model assumptions and not trapped inside of the standard interface. Maybe this is overcomplicating it, but "standard" data model codegen when you have a map that's {String:Whatever} spits out code that fits inside of go-ipld-prime such that the external API is consistent as if you're interacting with the data model. But it could also spit out an API that's not trapped in the data model, that you'd have to reach around to access and do things like Put([]byte, interface{}). Anyway, the more I think about this the more flexibility I want above the data model to build novel interfaces.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants