#self returning current object

1 messages · Page 1 of 1 (latest)

fervent bear
#

sometimes (i dare say often?) this is actually what i want, and to get it otherwise i'd have to re-construct it through the API, which might be a complicated chain

vital stirrup
#

🤔
I think I see what you mean.
I guess that's the different approach to what I took from there, because basically I'm loading the module itself as a dependency to get the types. And I was thinking to "just" rename it in some way, but I hit multiple walls while trying that.
So if I'm right what you suggest is to do that only on the SDK/codegen side and not like loading the module itself? (not sure if I'm clear enough)

fervent bear
#

Yeah, I think you want to keep the module name the same - and Solomon's suggestion to use dag.MyModule still makes sense. If you rename it at the schema layer that'll probably have bad caching semantics (your key will contain self instead of the real module name external clients use)

#

so I'm thinking self could still be a thing, but it could instead refer to the current live object that the function was called against. This is mechanically easy to do - when we're calling a module function, we already have the ID of its parent, so we can just pass it in somehow.

In code it could look something like this:

type MyModule struct {
  Foo int
}

func New(foo int) *MyModule {
  return &MyModule{foo}
}

func (m *MyModule) Bar(bar int) *Bar {
  dag.Self() // returns *dagger.MyModule with Foo filled in
  return &Bar{
    Foo: m.Foo,
    Bar: bar,
  }
}

type Bar struct {
  Foo int
  Bar int
}

func (b *Bar) Baz() {
  dag.Self() // returns *dagger.MyModuleBar (?) with Foo and Bar as expected
}
#

(I can move this to the github issue if you prefer)

vital stirrup
#

wouldn't it be confusing to have multiple dag.Self() that don't return the same thing? (if I understand it correctly)

fervent bear
#

yeah that part's a little odd for sure - like if you called Baz() "natively" instead of through a self-call, dag.Self() would be the wrong thing

#

if you consistently use self-calls it would work, but definitely a footgun for when you forget

#

i think there's something to this, but don't have a solid grasp on how it should be represented at the SDK layer thinkspin

#

a more explicit name might be dag.CurrentObject() (to match CurrentFunction, CurrentModule)

cold tusk
#

Since you can't dag.MyModuleBar() I'd only use dag.Self as an alias for the module's constructor (main object).

fervent bear
# cold tusk Since you can't `dag.MyModuleBar()` I'd only use `dag.Self` as an alias for the ...

that's my point though - there's no convenient way to call a sibling method on Bar if we only provide the module constructor, you would have to do dag.Self(b.Foo).Bar(b.Bar).[...]. If we're already supporting dag.MyModule I don't see much value in also providing dag.Self, besides the relatively narrow use case of renaming your module, but that's pretty easy to handle (and might even be done in the same s/MyModule/MyNewName)

cold tusk
#

Yeah, maybe leave this to the end and stabilize the rest.

vital stirrup
#

Yep, and we can also discuss (maybe?) to have other constructors, to simplify
One of the main usage is from MyModule to reference a type defined in the same module. But as there's no constructor it requires some utility function for that. Maybe could be automated, not sure.

#

But with all I tried, I'll put the Self on the side and re-focus on the main use case (without renaming)

cold tusk
#

Having other constructors is tricky. We're based on GraphQL and that's the way it works. Python has supported multiple constructors for a long time but it's as a way to define a function in an object without duplicating another object's constructor. Not usable directly from dag.

fervent bear
vital stirrup
#

I have a 404 on this URL (and repo)

fervent bear
# vital stirrup I have a 404 on this URL (and repo)

ah sorry, it's private atm. here's the snippet:

func (m *Daggerizer) evaluator() *dagger.Evaluator {
    var evals []*dagger.EvaluatorEval
    for _, project := range []string{
        "https://github.com/kpenfound/go-cli-example",
        "https://github.com/gin-gonic/gin",
        "https://github.com/openmeterio/openmeter",
    } {
        // TOOD: replace this with self-calls
        q := querybuilder.Query().Client(dag.GraphQLClient()).
            Select("daggerizer"). // this just 're-constructs' `m`
            Arg("source", m.Source).
            Select("daggerize"). // this is the field we want to call
            Arg("name", path.Base(project)).
            Arg("source", dag.Git(project).Head().Tree())
        evals = append(evals, (&dagger.EvaluatorEval{}).WithGraphQLQuery(q))
    }
    return dag.Evaluator().WithEvals(evals)
}